如何访问MediaBrowserServiceCompat服务的实例?

时间:2018-04-30 12:16:54

标签: android android-service android-mediaplayer android-support-library android-service-binding

我很惊讶地想要抓住源自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 :(得分:7)

正如您所发现的那样,$nodes_table_hostnames = $GetNodesResponse.properties.basic.nodes_table.node $nodes_table_status = $GetNodesResponse.properties.basic.nodes_table.state if($nodes_table_hostnames -contains "node1.prod.local:80" -and $nodes_table_status -eq "active") { Write-Output "Node matches and is Active" } 已经是一个绑定服务 - 您不能也不应该覆盖MediaBrowserServiceCompat

相反,您必须按照the documentationonBind()MediaBrowserServiceCompat联系。连接后,您可以通过以下方式触发自定义方法,例如MediaBrowserCompat

  1. the documentation
  2. 后的doMagic个实例中创建MediaControllerCompat
  3. 呼叫 sendCommand,传入MediaBrowserCompat字符串,用于唯一标识您的命令(例如command),您希望传递给方法的所有参数,以及doMagic如果您想要返回值。
  4. ResultReceiver注册的MediaSessionCompat.Callback中,覆盖onCommand()并处理命令(例如,通过调用MediaBrowserServiceCompat)。
  5. this blog post

    提供了这种方法的一个例子

答案 1 :(得分:0)

您可以尝试此解决方案(快速修复,不建议使用):

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);