Как получить доступ к экземпляру службы MediaBrowserServiceCompat?
Я на удивление изо всех сил пытаюсь заполучить экземпляр сервиса, который является производным от 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?
Чтобы быть понятным, функциональность воспроизведения работает нормально для меня. Вопрос заключается в том, как получить ссылку на службу, чтобы я мог выполнять вызовы моих пользовательских общедоступных методов в этой службе.
1 ответ
Как вы обнаружили, MediaBrowserServiceCompat
это уже связанная служба - вы не можете и не должны переопределять onBind()
,
Вместо этого вы должны подключиться к MediaBrowserServiceCompat
с MediaBrowserCompat
согласно документации. После подключения вы можете запускать пользовательские методы, такие как doMagic
от:
- Создать
MediaControllerCompat
от твоегоMediaBrowserCompat
экземпляр, следуя документации - Вызов
sendCommand
проходя вcommand
Строка, которая однозначно идентифицирует вашу команду (скажем,doMagic
), любые параметры, которые вы хотите передать в метод, иResultReceiver
если вы хотите вернуть значение. - в
MediaSessionCompat.Callback
зарегистрирован в вашемMediaBrowserServiceCompat
, переопределите onCommand() и обработайте команду (скажем, вызвавdoMagic
).
Пример такого подхода был предложен в этом блоге
Вы можете попробовать это решение (для быстрого исправления, не рекомендуется):
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);