I am currently working on a part of an app which has video and audio functionality, and started refactor the code base recently. The goal is to integrate MediaSession/ MediaController
and MediaBrowserService/ MediaBrowser
framework.
We use ExoPlayer
and PlayerControlView
more specific, the PlayerView for both video and audio components, and it requires the reference to the player instance for the PlayerControlView
:
/**
* Sets the {@link Player} to control.
*
* @param player The {@link Player} to control, or {@code null} to detach the current player. Only
* players which are accessed on the main thread are supported ({@code
* player.getApplicationLooper() == Looper.getMainLooper()}).
*/
public void setPlayer(@Nullable Player player) {...
However, under the android developers post and the documentation of MediaBrowserService
, the player instance should be contained under the service. In addition, the only way for the client site (MediaBrowser and MediaController) to talk to service it through the connect()
method and MediaBrowserConnectionCallback, which makes passing the instance of the player to the PlayerControlView (or the other way around) not possible.
I have tried using the various callbacks such as the MediaSessionCompat.Callback, but neither of the SimpleExoPlayer or the PlayerControlView are Parcelable.
In the traditional service, we uses Binder
to access the methods we declared within the service and do something like:
boolean attachPlayerControlView(PlayerControlView playerControlView) {
if (player != null) {
playerControlView.setPlayer(player);
return true;
}
return false;
}
However, this seems no possible with the MediaBrowserService/ MediaBrowser
framework. I checked the answer to this question, which indicates that using [sendCommand] is a way to call custom methods. But it also requires the parameters to be Parcelable.
To sum up, my question is, is there a way to have the PlayerControlView
access to the instance of SimpleExoPlayer
or the other way around under the MediaBrowserService
framework.
Many thanks ahead for any answer or comments.
In addition, the only way for the client site (MediaBrowser and MediaController) to talk to service it through the connect() method and MediaBrowserConnectionCallback, which makes passing the instance of the player to the PlayerControlView (or the other way around) not possible.
According to my understanding, this is not correct. You can always bind to MediaBrowserService in a traditional way i.e using IBinder to access Service. (Though I am not sure if this is the correct approach or not, otherwise I have to create a static MediaPlayer instance in Service).
I have faced a similar issue with Video Playback using MediaPlayer. I have bound to MediaBrowserService using IBinder and then fetched the MediaPlayer instance. In your service provide a method that returns a reference to MediaPlayer. Something like this:
private MediaPlayer mediaPlayer;
@Override
public IBinder onBind(Intent intent) {
if (intent.getAction().equals("YOUR_INTENT")) {
return new LocalBinder();
}
return super.onBind(intent);
}
public class LocalBinder extends Binder{
public AudioService getService(){
return AudioService.this;
}
}
public MediaPlayer getMediaPlayer() {
return mediaPlayer;
}
In your Activity/Fragment then bind to MediaBrowserService using IBinder. In my implementation, I have used MediaPlayer, but I think in similar ways it can be used for Exoplayer.
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback{
private MediaPlayer mediaPlayer;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private boolean isServiceBounded;
private boolean isSurfaceReady;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
isServiceBounded = true;
mediaPlayer = ((AudioService)service).getMediaPlayer();
if (isSurfaceReady) {
mediaPlayer.setDisplay(surfaceHolder);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
isServiceBounded = false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView = findViewById(R.id.surfaceView);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
bindService(new Intent("YOUR_INTENT"), serviceConnection, BIND_AUTO_CREATE);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
surfaceHolder = holder;
isSurfaceReady = true;
if (mediaPlayer != null) {
mediaPlayer.setDisplay(holder);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isSurfaceReady = false;
if (mediaPlayer != null) {
mediaPlayer.setDisplay(null);
}
surfaceHolder = null;
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(serviceConnection);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With