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

我在文字转语音应用程序中使用的耳机处理媒体按钮的代码在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”或我的代码有什么问题? 我完全不知所措。

更新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上测试的几个音乐播放器应用程序仍然可以使用媒体按钮,我只是无法弄清楚他们做了什么不同以使它们工作…我的应用程序的上下文不是播放音乐,而是用文本朗读文本语音服务,因此音乐播放器示例中的大量代码不适用。

解决了。 在“ Android 8.0行为更改 ”Google页面上,我们find以下文字:

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

更新

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

2017年10月10日更新2

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