Как получить доступ к экземпляру службы MediaBrowserServiceCompat? - PullRequest
0 голосов
/ 30 апреля 2018

Я удивительно изо всех сил пытаюсь заполучить экземпляр службы, которая получена из MediaBrowserServiceCompat.

Для типичной услуги, для достижения которой используется местное связующее

class MyService extends MediaBrowserServiceCompat {
  class MyBinder extends Binder {
    public MyService getService() {
      return MyService.this;
    }

  private final MyBinder binder = new MyBinder();

  @Override
  public IBinder onBind(Intent intent) {
    return binder;
  }

  public void doMagic() { // <-- How to call this from activity?
    // ...
  }
}

// At the activity, for example, this binder is retrieved through 
// `onServiceConnected()`, typecast to `MyBinder` and thus 
// `getService()` gets us the service instance.

Однако это не работает для службы, полученной из MediaBrowserServiceCompat.

Когда я пытаюсь предоставить локальное связующее устройство, как показано выше, служба аварийно завершает работу, поскольку MediaBrowserServiceCompat ожидает своего собственного пользовательского связывателя с дополнительными функциями. Вот трассировка стека краха

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference
    at android.os.Binder.queryLocalInterface(Binder.java:254)
    at android.service.media.IMediaBrowserService$Stub.asInterface(IMediaBrowserService.java:31)
    at android.media.browse.MediaBrowser$MediaServiceConnection.onServiceConnected(MediaBrowser.java:793)
    at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1223)
    at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1240)
    at android.os.Handler.handleCallback(Handler.java:746)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5443)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

Я попытался обернуть связыватель из суперкласса MediaBrowserServiceCompat, как показано ниже, но все равно это не сработало.

class MyService extends MediaBrowserServiceCompat {
  class MyBinder extends Binder {
    public MyService getService() {
      return MyService.this;
    }

  private final WrappingBinder<MyService> binder;

  @Override
  public IBinder onBind(Intent intent) {
    if (binder == null) {
      binder = new WrappingBinder(super.onBind(intent));
    }

    return binder;
  }

  public void doMagic() { // <-- How to call this from activity or elsewhere?
    // ...
  }
}

Интересно, какой подход следует использовать для доступа к экземпляру службы MediaBrowserServiceCompat?

Для ясности, у меня нормально работает функция воспроизведения. Вопрос в том, как получить ссылку на службу, чтобы я мог выполнять вызовы для своих пользовательских общедоступных методов в этой службе.

Ответы [ 2 ]

0 голосов
/ 05 января 2019

Вы можете попробовать это решение (для быстрого исправления, не рекомендуется):

private final MyBinder myBinder = new MyBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
    if (intent.getBooleanExtra("is_binding", false)) {
        return myBinder;
    }
    return super.onBind(intent);
}

// Bind service in your activity:

Intent intent = new Intent(this, MyPlaybackService.class);
intent.putExtra("is_binding", true);

bindService(intent, this, Context.BIND_AUTO_CREATE);
0 голосов
/ 30 апреля 2018

Как вы обнаружили, MediaBrowserServiceCompat - это уже связанная служба - вы не можете и не должны переопределять onBind().

Вместо этого вы должны подключиться к MediaBrowserServiceCompat с MediaBrowserCompat согласно документации . После подключения вы можете запускать пользовательские методы, такие как doMagic:

  1. Создайте MediaControllerCompat из вашего MediaBrowserCompat экземпляра, следуя документации
  2. Вызов sendCommand, передавая строку command, которая однозначно идентифицирует вашу команду (скажем, doMagic), любые параметры, которые вы хотите передать методу, и ResultReceiver, если вы хотите вернуть значение.
  3. В MediaSessionCompat.Callback, зарегистрированном с помощью MediaBrowserServiceCompat, переопределите onCommand () и обработайте команду (скажем, путем вызова doMagic).

Пример такого подхода был предложен в этом блоге

...