14

我在 Text-to-Speech 应用程序中使用的用于处理来自耳机的媒体按钮的代码在 Android API 22 到 25 下运行良好(在旧版本的 Android 中,它们由其他现已贬值的方式处理)。然而,在 Android 8“Oreo”下,无论是公开测试版还是最终版本,它都不起作用。以下是相关代码:

当服务启动时,我创建 MediaSessionCompact 对象:

        mSession = new MediaSessionCompat(getApplicationContext(), "my.package.name._player_session");
        mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mSession.setActive(true);
        mSession.setCallback(myMediaSessionCallback);
        PlaybackStateCompat state = new PlaybackStateCompat.Builder()
                .setActions(ACTION_PLAY_PAUSE | ACTION_PLAY | ACTION_PAUSE |
                        ACTION_SKIP_TO_NEXT | ACTION_SKIP_TO_PREVIOUS |
                        ACTION_FAST_FORWARD | ACTION_REWIND
                )
                .setState(PlaybackStateCompat.STATE_PAUSED, 0 /*PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN*/, 1f)
                .build();
        mSession.setPlaybackState(state);

当然定义了会话媒体回调:

private MediaSessionCompat.Callback myMediaSessionCallback = new MediaSessionCompat.Callback() {
    @Override
    public boolean onMediaButtonEvent(Intent mediaButtonIntent) {
        // The log output below never appears on "Oreo", nothing comes here.
        Log.d(TAG, "callback onMediaButtonEvent() Compat");
        MediaButtonIntentReceiver.handleIntent(mediaButtonIntent.getAction(), (KeyEvent) mediaButtonIntent.getParcelableExtra(Intent.EXTRA_KEY_EVENT));
        return true;
    }

    @Override
    public void onSkipToNext() {
        //...
    }
    // etc. other overrides
};

我还尝试了 PendingIntent,使用 MediaButtonReceiver.buildMediaButtonPendingIntent() 并为我感兴趣的所有操作设置 mSession.setMediaButtonReceiver(pendingIntent),然后在我的服务 onStartCommand() 中调用 MediaButtonReceiver.handleIntent(mSession, intent):

// still in the same service:            
mSession.setMediaButtonReceiver(
            MediaButtonReceiver.buildMediaButtonPendingIntent(
                this,
                mMediaButtonReceiverComponentName,
                ACTION_PLAY));


mSession.setMediaButtonReceiver(
            MediaButtonReceiver.buildMediaButtonPendingIntent(
                this,
                mMediaButtonReceiverComponentName,
                ACTION_PAUSE));


mSession.setMediaButtonReceiver(
            MediaButtonReceiver.buildMediaButtonPendingIntent(
                this,
                mMediaButtonReceiverComponentName,
                ACTION_PLAY_PAUSE));

在服务 onStartCommand() 中:

@Override 
public int onStartCommand(Intent intent, int flags, int startId) {
    // ...
    if (intent != null) {
        MediaButtonReceiver.handleIntent(mSession, intent);
        // ...
    }
    return START_NOT_STICKY;
}

没什么,媒体按钮按下事件完全是愚蠢的。“O”或我的代码有什么问题???我完全感到困惑。

2017 年 8 月 32 日更新

我还创建了一个简单但有效的应用程序项目来演示该问题,请参阅:https ://github.com/gregko/PlayerServiceSample 。此项目在 Android 5.x 到 7.x 下在耳机上按下媒体按钮时显示 LogCat 输出,但在 Android 8“Oreo”下完全失败。

2017 年 9 月 1 日更新 Android 问题跟踪器上现在有一个关于此问题的未解决问题,我在https://issuetracker.google.com/issues/65175978提交了该问题。媒体按钮仍然可以在我在 Oreo 上测试的几个音乐播放器应用程序中工作,我只是不知道它们做了什么不同的工作以使它们工作......我的应用程序的上下文不是播放音乐,而是用文本大声朗读文本到语音服务,因此音乐播放器示例中的许多代码不适用。

4

1 回答 1

19

解决了。在“ Android 8.0 Behavior Changes ”谷歌页面上,我们找到了这段文字:

在 Android 8.0(API 级别 26)中,媒体按钮事件的处理有所不同:

  1. UI 活动中媒体按钮的处理没有改变:前台活动仍然优先处理媒体按钮事件。
  2. 如果前台活动不处理媒体按钮事件,系统会将事件路由到最近在本地播放音频的应用程序。在确定哪个应用程序接收媒体按钮事件时,不会考虑媒体会话的活动状态、标志和播放状态。
  3. 如果应用程序的媒体会话已被释放,则系统将媒体按钮事件发送到应用程序的 MediaButtonReceiver(如果有)。
  4. 对于其他所有情况,系统都会丢弃媒体按钮事件。

为了让我的小样本工作,我所要做的就是用 MediaPlayer 播放一些声音。显然使用 Text-to-Speech API 播放声音不符合条件,在我看来这是一个错误。

这是我添加到我的简单示例中以使其工作的代码,从原始资源目录播放一个非常简短且无声的 WAV 文件:

    final MediaPlayer mMediaPlayer;
    mMediaPlayer = MediaPlayer.create(this, R.raw.silent_sound);
    mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {
            mMediaPlayer.release();
        }
    });
    mMediaPlayer.start();

更新

在https://issuetracker.google.com/issues/65344811向 Android 问题跟踪器提交了错误报告

更新 2,2017 年 10 月 10 日

谷歌现在表示,奥利奥在这方面的行为是“设计的”,不会修复它。阅读上面问题跟踪器帖子末尾附近的回复。我必须说我很失望。

于 2017-09-01T22:12:29.083 回答