【Audio&Video】响应媒体按钮(12)

媒体按钮是Android设备和其他外围设备上的硬件按钮,例如,蓝牙耳机上的暂停/播放按钮。当用户按下媒体按钮时,Android会生成一个KeyEvent包含标识该按钮的密钥代码。媒体按钮KeyEvent的键码是以KEYCODE_MEDIA(例如KEYCODE_MEDIA_PLAY)开头的常量。

按照以下优先顺序,应用程序应能够处理三种媒体按钮事件:

当应用程序的UI活动可见时
隐藏UI活动并且应用程序的媒体会话处于活动状态时
当UI活动隐藏并且应用程序的媒体会话处于非活动状态并需要重新启动时

处理前台活动中的媒体按钮


前台活动在其onKeyDown() 方法中接收媒体按钮键事件。根据Android的运行版本,系统可以通过两种方式将事件路由到媒体控制器:

如果您正在运行Android 5.0(API级别21)或更高版本,请致电 FLAG_HANDLES_MEDIA_BUTTONS MediaBrowserCompat.ConnectionCallback.onConnected。这会自动调用您的媒体控制器 dispatchMediaButtonEvent(),它将关键代码转换为媒体会话回调。
在Android 5.0(API级别21)之前,您需要修改onKeyDown()以自行处理事件。(请参阅处理活动媒体会话中的媒体按钮以获取详细信息。)以下代码片段显示如何拦截键码并调用dispatchMediaButtonEvent()。请务必返回true以表明事件已处理完毕:

@Override
boolean onKeyDown(int keyCode, KeyEvent event) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
          return super.onKeyDown(keyCode, event);
        }
        switch (keyCode) {
          case KeyEvent.KEYCODE_MEDIA_PLAY:
                  yourMediaController.dispatchMediaButtonEvent(event);
                  return true;
        }
        return super.onKeyDown(keyCode, event);
 }

寻找媒体会议


如果前台活动未处理该事件,则Android会尝试查找可处理该事件的媒体会话。再次,根据Android的运行版本,有两种方法可以搜索媒体会话:

如果您运行的是Android 8.0(API级别26)或更高版本,则系统会尝试使用本地播放音频的MediaSession查找最后一个应用。如果会话仍处于活动状态,则Android将事件直接发送给它。否则,如果会话不是活动的,并且它有一个mediabutton接收器,则Android将该事件发送给接收方,这将重新启动会话,因此它可以接收事件。(有关详细信息,请参阅使用媒体按钮重新启动非活动媒体会话。)如果会话没有媒体按钮接收器,系统会放弃媒体按钮事件并且不会发生任何事情。逻辑如下图所示:

【Audio&Video】响应媒体按钮(12)

在Android 8.0(API级别26)之前,系统尝试将事件发送到活动媒体会话。如果存在多个活动媒体会话,则Android会尝试选择准备播放(缓冲/连接),正在播放或已暂停的媒体会话,而不是已停止的媒体会话。(请参阅 处理活动媒体会话中的媒体按钮以 获取更多详细信息。)如果没有活动会话,Android会尝试将该事件发送到最近活动的会话。(有关详细信息,请参阅使用媒体按钮重新启动非活动媒体会话。)逻辑如下图所示:
【Audio&Video】响应媒体按钮(12)

处理活动媒体会话中的媒体按钮


在Android 5.0(API级别21)及更高版本上,Android会通过调用自动将媒体按钮事件分派到活动媒体会话 onMediaButtonEvent()。默认情况下,此回调会将KeyEvent转换为适合的媒体会话回调方法,以匹配键码。

扫描二维码关注公众号,回复: 1637976 查看本文章

在Android 5.0(API级别21)之前,Android会通过广播ACTION_MEDIA_BUTTON动作的意图来处理媒体按钮事件。你的应用必须注册一个BroadcastReceiver来拦截这些意图。这 MediaButtonReceiver 门课是专门为此设计的。它是Android media-compat库中的一个便利类, 它处理ACTION_MEDIA_BUTTON并将传入Intents转换为适当的MediaSessionCompat.Callback方法调用。

A MediaButtonReceiver是短暂的BroadcastReceiver。它将传入的意图转发到管理媒体会话的服务。如果您想在早于Android 5.0的系统中使用媒体按钮,则必须MediaButtonReceiver在清单中包含MEDIA_BUTTON意向过滤器。:

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

该BroadcastReceiver意图×××前锋。要解析该意图并生成回传到您的媒体会话,请将该MediaButtonReceiver.handleIntent()方法包含在您的服务中onStartCommand()。这将密钥代码转换为适当的会话回调方法。

private MediaSessionCompat mMediaSessionCompat = ...;

 public int onStartCommand(Intent intent, int flags, int startId) {
   MediaButtonReceiver.handleIntent(mMediaSessionCompat, intent);
   return super.onStartCommand(intent, flags, startId);
 }

注意:如果您没有MediaBrowserServiceCompat,您还可以将ACTION_MEDIA_BUTTON意图过滤器添加到任何服务。有关MediaButtonReceiver更多信息,请参阅 文档。

使用媒体按钮重新启动非活动媒体会话


如果Android能够识别最后一个活动媒体会话,它会尝试通过将ACTION_MEDIA_BUTTONIntent 发送到清单注册组件(例如服务或BroadcastReceiver)来重新启动会话。

这可让您的应用重新开始播放,而其UI不可见,大多数音频应用都是如此。

这一行为在您使用时会自动启用MediaSessionCompat。如果您使用Android框架MediaSession或Support Library 24.0.0至25.1.1,您必须致电setMediaButtonReceiver以让媒体按钮重新启动非活动媒体会话。

您可以通过设置空媒体按钮接收器来在Android 5.0(API级别21)及更高版本中禁用此行为:

    // Create a MediaSessionCompat
    mMediaSession = new MediaSessionCompat(context, LOG_TAG);
    mMediaSession.setMediaButtonReceiver(null);

注意:对于在早于Android 5.0(API级别21)的系统中运行的应用程序,MediaButtonReceiver注册处理活动会话的媒体按钮时,会话处于非活动状态时也会收到媒体按钮事件。无法禁用此行为。

自定义媒体按钮处理程序


用于onMediaButtonEvent()提取密钥代码的默认行为,并使用媒体会话的当前状态和支持的操作列表来确定要调用的方法。例如,KEYCODE_MEDIA_PLAY调用onPlay()。

为了在所有应用中提供一致的媒体按钮体验,您应该使用默认行为,并仅针对特定目的进行偏离。如果媒体按钮需要自定义处理,请覆盖您的回调 onMediaButtonEvent() 方法,提取KeyEvent使用情况 intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT),自行处理事件并返回true。

概要


要正确处理所有Android版本中的媒体按钮事件,您必须指定FLAG_HANDLES_MEDIA_BUTTONS 何时创建媒体会话。

另外,根据您计划支持的Android版本,您还必须满足以下要求:

在Android 5.0或更高版本中运行时:

呼叫MediaControllerCompat.setMediaController()从媒体控制器onConnected()回调
要允许媒体按钮重新启动非活动会话,请MediaButtonReceiver通过调用 setMediaButtonReceiver()并传递它来动态创建一个PendingIntent
在早于Android 5.0的系统中运行时:

覆盖活动onKeyDownEvent()来处理媒体按钮
静态创建一个MediaButtonReceiver通过将其添加到应用程序的清单

联系我

QQ:94297366
微信打赏:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ

公众号推荐:

【Audio&Video】响应媒体按钮(12)

猜你喜欢

转载自blog.51cto.com/4789781/2130466