带有 ExoPlayer 和 PlayerControlView 的 MediaBrowserService - 如何从 UI (PlayerControlView) 访问播放器实例?

Mik*_*Hsu 9 android exoplayer mediabrowserservice mediabrowserservicecompat mediasession

我目前正在开发具有视频和音频功能的应用程序的一部分,最近开始重构代码库。目标是集成MediaSession/ MediaControllerMediaBrowserService/ MediaBrowser框架。

我们使用ExoPlayerPlayerControlView更具体的PlayerView的视频和音频组件,它需要提及的播放器实例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) {...
Run Code Online (Sandbox Code Playgroud)

但是,在Android开发者职位文档MediaBrowserService,播放器实例应在服务下载。此外,客户端站点(MediaBrowser 和 MediaController)通过connect()方法和MediaBrowserConnectionCallback为其提供服务的唯一方法,这使得将播放器的实例传递给 PlayerControlView(或其他方式)是不可能的。

我曾尝试使用各种回调,例如MediaSessionCompat.Callback,但SimpleExoPlayerPlayerControlView都不是 Parcelable。

在传统服务中,我们使用Binder访问我们在服务中声明的方法并执行以下操作:

boolean attachPlayerControlView(PlayerControlView playerControlView) {
            if (player != null) {
                playerControlView.setPlayer(player);
                return true;
            }
            return false;
        }
Run Code Online (Sandbox Code Playgroud)

然而,这对于MediaBrowserService/ MediaBrowser框架来说似乎是不可能的。我检查了这个问题的答案,它表明使用 [sendCommand] 是一种调用自定义方法的方法。但它也要求参数是 Parcelable。

总而言之,我的问题是,有没有办法PlayerControlView访问框架SimpleExoPlayer下的实例或其他方式MediaBrowserService

非常感谢您的任何回答或评论。

ARU*_*NGH 2

此外,客户端站点(MediaBrowser 和 MediaController)通过 connect() 方法和 MediaBrowserConnectionCallback 与服务进行通信的唯一方法,这使得将播放器实例传递给 PlayerControlView(或相反)是不可能的。

据我了解,这是不正确的。您始终可以以传统方式绑定到 MediaBrowserService,即使用 IBinder 访问 Service。(虽然我不确定这是否是正确的方法,否则我必须在 Service 中创建一个静态 MediaPlayer 实例)。

我在使用 MediaPlayer 播放视频时遇到了类似的问题。我已使用 IBinder 绑定到 MediaBrowserService,然后获取 MediaPlayer 实例。在您的服务中提供一个返回 MediaPlayer 引用的方法。像这样的东西:

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;
}
Run Code Online (Sandbox Code Playgroud)

然后在您的 Activity/Fragment 中使用 IBinder 绑定到 MediaBrowserService。在我的实现中,我使用了 MediaPlayer,但我认为它可以以类似的方式用于 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);
}
Run Code Online (Sandbox Code Playgroud)

}