处理 android 锁屏上的音量变化?

Handling volume change on android lockscreen?

我想做的是,能够在 android 4.4 的锁屏上捕获音量 up/down 按钮操作。

Google Cast Design Checklist 文档描述了锁屏要求 "Provide access to the volume control via hardware buttons"。我尝试了多种方法来处理锁定屏幕上的硬件音量按钮,但其中 none 有效。

  1. onKeyDown/dispatchKeyEvent - 我试图覆盖 Activity 上的 onKeyDown 和 dispatchKeyEvent 方法,但是 none这些是在锁屏上执行的,这些仅在我的应用程序处于焦点时才有效。

  2. Settings.System.CONTENT_URI/ContentObserver - 在主 activity 的内容解析器上注册内容观察器确实捕获了系统设置更改,但在锁屏上也不会发生。

  3. android.intent.action.MEDIA_BUTTON - 在清单中有这个过滤器,我能够从锁屏接收 play/pause 操作,但是没有音量变化事件.

  4. android.media.VOLUME_CHANGED_ACTION - 在清单中有这个过滤器,这个事件在我的 BroadcastReceiver 中收到,不幸的是它的额外值在锁屏上永远不会改变。当我不断按下音量按钮时,返回的 android.media.EXTRA_VOLUME_STREAM_VALUE 保持不变(即始终为 1),即使我的广播接收器收到了 CHANGED 操作。

  5. CastVideos-android - 参考 android 发送器应用程序似乎能够控制接收器的音量,即使从发件人锁定屏幕,但是即使在 Cast.CastApi.setVolume() 周围到处都是断点之后,这些也不会被选中。所以看起来命令是从我无法定位的地方发送到接收器的。

我还可以看到其他一些应用能够捕获硬件音量键,即 Play Music 应用。所以我的设备肯定有能力......

任何人都可以提出任何可行的解决方案吗?

您需要使用 RemoteControlClient(在棒棒糖之前)或最近引入的 MediaSession。例如,查看 CastCompanionLibrary, VideoCastManager#setUpRemoteControl() 方法,其中 RCC 注册到 MediaRouter。如果使用 MediaSession,则需要使用 MediaRouter.

注册 MediaSession

最后我好像少了一行代码:

MediaRouter.getInstance(context).addRemoteControlClient(remoteControlClient);

MediaRouter.getInstance(activity).setMediaSession(session.getMediaSession());

这里是我为 4.0+ 实现的更多代码:

import android.media.AudioManager;
import android.media.RemoteControlClient;
import android.support.v7.media.MediaRouter;

remoteControlClient = new RemoteControlClient(pendingIntent);
remoteControlClient.setTransportControlFlags(RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE);

audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.registerMediaButtonEventReceiver(receiver);
audioManager.registerRemoteControlClient(remoteControlClient);

MediaRouter.getInstance(context).addRemoteControlClient(remoteControlClient);

对于 5.0+:

import android.media.AudioManager;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v7.media.MediaRouter;

session = new MediaSessionCompat(activity, TAG);
session.setPlaybackToLocal(AudioManager.STREAM_MUSIC);

MediaRouter.getInstance(activity).setMediaSession(session.getMediaSession());

有趣的是,有一些黑魔法可以在内部控制接收器音量,而您自己的 Cast.CastApi.setVolume() 调用根本不涉及