MediaBrowserService с ExoPlayer и PlayerControlView - как получить доступ к экземпляру проигрывателя из пользовательского интерфейса (PlayerControlView)?

В настоящее время я работаю над частью приложения, которое имеет функции видео и аудио, и недавно начал рефакторинг базы кода. Цель - интегрироватьMediaSession/ MediaController а также MediaBrowserService/ MediaBrowser фреймворк.

Мы используем ExoPlayer а также PlayerControlViewболее конкретно, 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) {...

Тем не менее, под андроид разработчиков размещать и документации поMediaBrowserService, экземпляр проигрывателя должен содержаться в службе. Кроме того, единственный способ для клиентского сайта (MediaBrowser и MediaController) взаимодействовать с ним черезconnect()метод и MediaBrowserConnectionCallback, что делает невозможной передачу экземпляра плеера в PlayerControlView (или наоборот).

Я пробовал использовать различные обратные вызовы, такие как MediaSessionCompat.Callback, но ни SimpleExoPlayer, ни PlayerControlView не являются Parcelable.

В традиционном сервисе мы используем Binder чтобы получить доступ к методам, которые мы объявили внутри службы, и сделать что-то вроде:

boolean attachPlayerControlView(PlayerControlView playerControlView) {
            if (player != null) {
                playerControlView.setPlayer(player);
                return true;
            }
            return false;
        }

Однако это кажется невозможным с MediaBrowserService/ MediaBrowserфреймворк. Я проверил ответ на этот вопрос, который указывает на то, что использование [sendCommand] - это способ вызова пользовательских методов. Но для этого также требуется, чтобы параметры были Parcelable.

Подводя итог, мой вопрос: есть ли способ получить PlayerControlView доступ к экземпляру SimpleExoPlayer или наоборот под MediaBrowserService фреймворк.

Большое спасибо за любой ответ или комментарии.

0 ответов

Кроме того, единственный способ для клиентского сайта (MediaBrowser и MediaController) взаимодействовать с сервисом через метод connect() и MediaBrowserConnectionCallback, что делает невозможной передачу экземпляра плеера в PlayerControlView (или наоборот).

Насколько я понимаю, это неверно. Вы всегда можете привязаться к MediaBrowserService традиционным способом, то есть используя IBinder для доступа к Service. (Хотя я не уверен, правильный ли это подход или нет, в противном случае мне нужно создать статический экземпляр MediaPlayer в службе).

Я столкнулся с аналогичной проблемой при воспроизведении видео с помощью MediaPlayer. Я привязался к MediaBrowserService с помощью IBinder, а затем получил экземпляр 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;
}

Затем в своем Activity/Fragment привяжите к MediaBrowserService с помощью IBinder. В своей реализации я использовал 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);
}

}

Другие вопросы по тегам