在TV定制系统中,你是不是会碰上过这样的需求,通过遥控器按键一键触发某些操作或者打开某个页面,这个需要怎么实现呢?

今天就给大家带来其中一种实现方案:GlobalKey

那我们首先来看下 GlobalKey 配置需要做些什么?

在 global_keys.xml 中进行配置

在文件:frameworks/base/core/res/res/xml/global_keys.xml 中进行如下所示配置: 可以查看源码:http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/res/res/xml/global_keys.xml

<key keyCode="KEYCODE_VOLUME_UP" component="com.android.example.keys/.VolumeKeyHandler" />

其中 keyCode 表示需要配置的按键,component 表示需要打开的组件

注册静态广播监听 Intent.ACTION_GLOBAL_BUTTON

Intent.ACTION_GLOBAL_BUTTON -> “android.intent.action.GLOBAL_BUTTON”

public class GlobalKeyBroadcastReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
      if ("android.intent.action.GLOBAL_BUTTON".equals(intent.getAction())) {
          KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
          int keyCode = event.getKeyCode();
          // do something
      }
    }
}

GlobalKeyBroadcastReceivermanifest 中进行注册

<receiver android:name=".receiver.GlobalKeyBroadcastReceiver">
    <intent-filter android:priority="20">
        <action android:name="android.intent.action.GLOBAL_BUTTON" />
    </intent-filter>
</receiver>

这样就能监听到对应按键按下时应该怎么处理了。

到这里你就已经完成了一大步了,但是为了学习,我们得深入了解这个配置是怎么起作用的?

谁加载了这个 xml 呢? 这个广播又是谁发出来的?

慢慢的就会发现 GlobalKeyManager 这个类了,类的内容已经给大家准备好,直接上链接:

http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/policy/GlobalKeyManager.java

其中

private void loadGlobalKeys(Context context)

这个方法实现了 xml 的加载,并将结果放到一个 map 中备用

然后你会发现里面有个方法:

/**
 * Broadcasts an intent if the keycode is part of the global key mapping.
 *
 * @param context context used to broadcast the event
 * @param keyCode keyCode which triggered this function
 * @param event keyEvent which trigged this function
 * @return {@code true} if this was handled
 */
boolean handleGlobalKey(Context context, int keyCode, KeyEvent event) {
    if (mKeyMapping.size() > 0) {
        ComponentName component = mKeyMapping.get(keyCode);
        if (component != null) {
           Intent intent = new Intent(Intent.ACTION_GLOBAL_BUTTON)
                    .setComponent(component)
                    .setFlags(Intent.FLAG_RECEIVER_FOREGROUND)
                    .putExtra(Intent.EXTRA_KEY_EVENT, event);
            context.sendBroadcastAsUser(intent, UserHandle.CURRENT, null);
            return true;
        }
    }
    return false;
}

这个方法应该是在什么地方调用了,发现在