Android"O"(Oreo,8)媒体按钮问题

gre*_*gko 11 android bluetooth android-8.0-oreo media-buttons

我在文字转语音应用程序中使用的耳机处理媒体按钮的代码在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);
Run Code Online (Sandbox Code Playgroud)

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

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
};
Run Code Online (Sandbox Code Playgroud)

我还尝试了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));
Run Code Online (Sandbox Code Playgroud)

并在服务onStartCommand()中:

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

没什么,媒体按钮按下事件是完全愚蠢的."O"或我的代码有什么问题?我完全不知所措.

更新8/32/2017

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

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

gre*_*gko 10

解决了.在" Android 8.0行为更改 "Google页面上,我们找到以下文字:

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

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

我需要做的就是让我的琐碎样本工作就是用MediaPlayer播放一些声音.显然使用文字转语音API播放声音不合格,我认为这是一个错误.

这是我添加到我的简单示例中以使其工作的代码,从Raw资源目录中播放一个非常简短且无声的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();
Run Code Online (Sandbox Code Playgroud)

更新

已将错误报告提交至Android问题跟踪器,网址https://issuetracker.google.com/issues/65344811

2017年10月10日更新2

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