第二次调用 setActive(true) 时,App 不会成为首选的 MediaButtonReceiver

App does not become the preferred MediaButtonReceiver when calling setActive(true) a second time

我已尝试根据 Google's talk

实现媒体按钮控制

我在清单中设置了接收器:

<receiver android:name="android.support.v4.media.session.MediaButtonReceiver">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

<service android:name=".player.PlayFileService">
    <intent-filter>
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</service>

在服务的 onCreate() 中创建 MediaSessionCompat

    mediaSession = new MediaSessionCompat(getApplicationContext(), "SOUNDPROCESS");
    mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
    PlaybackStateCompat ps = new PlaybackStateCompat.Builder()
            .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE | PlaybackStateCompat.ACTION_PLAY_PAUSE)
            .build();
    mediaSession.setPlaybackState(ps);
    mediaSession.setCallback(new MediaSessionCompat.Callback() {
        @Override
        public void onPlay() { ...
           }
    });

并处理 onStartCommand()

中的意图
MediaButtonReceiver.handleIntent(mediaSession, intent);

然后我在获得音频焦点时调用 setActive(true);,在停止播放时调用 setActive(false);。这是第一次工作,我的应用程序成为首选媒体按钮接收器并接收回调。

但是,如果我停止在我的应用程序中播放,请进入另一个应用程序,例如 Google 播放音乐并在那里开始播放,然后 return 到我的应用程序并调用 setActive(true) Google 播放音乐继续收到回调,媒体按钮在我的应用程序中不起作用。

根据我的理解,最后一次调用 setActive(true) 应该优先。我已经验证 isActive() return 是真的。我也可以通过每次创建一个新的 MediaSessionCompat 来解决这个问题,但这似乎并不理想。

如何让我的应用成为我每次调用时首选的媒体按钮接收器?setActive(true)

更新:重现问题的最小项目:https://github.com/svenoaks/MediaButtonDemo.git

重现步骤:

  1. 运行 应用程序,按 PLAY 按钮。 setActive(true) 被调用并且 MediaButtonReceiver 现在是首选媒体按钮。
  2. 按有线或无线耳机或其他设备上的 play/pause 按钮 媒体按钮。 Toast 显示表明回调正在工作。
  3. 开始在另一个应用程序上播放,例如 Google Play Music 支持媒体按钮。在此应用程序上按暂停键。
  4. 演示应用不能再成为首选媒体按钮接收器, 即使再次按下 PLAY 按钮,调用 setActive(true) 再次。其他应用始终响应媒体按钮。

这是在 Android 6.0.

上测试的

我的观察:(没有足够的声誉来发表评论,抱歉,但我可以回复此答案的评论)

  1. 'Run app, press the PLAY button. setActive(true) is called and MediaButtonReceiver is now the preferred media button':因为Android首先将媒体按钮事件派发到前台activity。

  2. 'Start playback on another app.......Press pause on this app........then return to my app and call setActive(true) ':

a) 如果您在播放 GooglePlay 音乐之前调用了 onStop 监听器,那么当您按下任何媒体按钮时,您的媒体会话将不会激活(直到再次调用 onPlay),因此当前会话是 Google Play gets played.

b) 如果您没有调用 onStop,则有 2 个活动会话(应用程序的第一个会话和 Google Play 的第一个会话。除非调用 OnPlay,否则不会调用第二个会话再次)。根据文档,如果有多个活动媒体会话,Android 会尝试选择准备播放 (buffering/connecting)、正在播放或暂停的媒体会话,而不是已停止的媒体会话。所以 GooglePlay 是暂停状态的最新活动会话并开始播放。

c) 如果您调用了 onStop(因此设置了 Active(false)),并且如果 GooglePlayMusic 也设置了 Active(false),并且您没有再次单击 onPlay,那么在这种情况下 GooglePlayMusic 将从 "If there is no active session, Android tries to send the event to the most recently active session. On Android 5.0 (API level 21) or later the event is only sent to sessions that have called setMediaButtonReceiver()."

开始播放

你有设置MediaButtonReceiver()吗?

https://developer.android.com/guide/topics/media-apps/mediabuttons.html 请看一下

使这项工作正常进行的关键是在您的应用程序每次开始播放或暂停时正确设置 PlaybackState(当另一个应用程序获得音频会话并激活它自己的 MediaSession。没有这个,就会出现上面的问题。另外,对于Android 4.4及更低版本,必须设置FLAG_HANDLES_TRANSPORT_CONTROLS,否则会出现同样的问题。