I would like to create Activity with video player to play online stream using MediaPlayer class and SurfaceView to display. I'm creating MediaPlayer in separate Service so after screen rotation player don't have to be created again and don't have to connect to stream. My problem is that I don't know how to write Activity so my service wouldn't start every time after screen rotation.
My code below, in onStart() I start service but I don't know how to change it so it didn't start every time.
public class VideoPlayerActivity extends Activity implements SurfaceHolder.Callback {
private String path;
private SurfaceHolder vidHolder;
private SurfaceView vidSurface;
private VideoService videoService;
private Intent playIntent;
private boolean videoBound = false;
private ServiceConnection musicConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
VideoService.VideoBinder binder = (VideoService.VideoBinder) service;
videoService = binder.getService();
videoService.setUrl(path);
videoBound = true;
if (vidHolder != null && videoService.getMediaPlayer() != null) {
videoService.getMediaPlayer().setDisplay(vidHolder);
videoService.playVideo();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
videoBound = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
path = "https://archive.org/download/ksnn_compilation_master_the_internet/ksnn_compilation_master_the_internet_512kb.mp4"; //TODO tmp
playIntent = new Intent(this, VideoService.class);
bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
startService(playIntent);
vidSurface = (SurfaceView) findViewById(R.id.surfView);
vidHolder = vidSurface.getHolder();
vidHolder.addCallback(VideoPlayerActivity.this);
}
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
if (videoService != null && videoService.getMediaPlayer() != null) {
videoService.getMediaPlayer().setDisplay(vidHolder);
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
Log.d("ServiceConnection", "surfaceChanged " + i + " " + i1 + " " + i2);
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
Log.d("ServiceConnection", "surfaceDestroyed");
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(musicConnection);
stopService(playIntent);
videoService = null;
}
}
Service class:
public class VideoService extends Service implements OnPreparedListener {
private MediaPlayer player;
private String path;
private final IBinder musicBind = new VideoBinder();
@Override
public void onCreate() {
Log.d("VideoService", "onCreate");
super.onCreate();
player = new MediaPlayer();
initMusicPlayer();
}
@Override
public IBinder onBind(Intent intent) {
return musicBind;
}
@Override
public boolean onUnbind(Intent intent){
player.stop();
player.release();
return false;
}
public void initMusicPlayer() {
player.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setOnPreparedListener(this);
}
public void playVideo() {
try {
player.setDataSource(path);
player.prepareAsync();
} catch (IOException e) {}
}
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
public void setUrl(String url) {
path = url;
}
public MediaPlayer getMediaPlayer() {
return player;
}
public class VideoBinder extends Binder {
public VideoService getService() {
return VideoService.this;
}
}
}
You could either check for savedInstanceState
being null to only start the service if the Activity is freshly created
if (savedInstanceState == null) {
startService...
}
or handle screen rotation yourself by adding
android:configChanges="orientation|keyboardHidden|screenSize"
to your Activity in manifest. Like this onCreate will not be called on rotation any more.