探讨Android实现后台(Service)按键监听的功能

一般来说需要做这个功能的大多数是机顶盒或者智能电视,也就是AndroidTv。刚好这两天公司的机顶盒有这么一个需求,针对遥控器某些特殊按键,实现按键的监听,并实现相应的功能。研究了一下,大概有这么一些办法。
  第一种办法是广播,一般来说系统对于音量键和Home键会发送广播,我们可以再广播中监听这些按键信息。具体的IntentFilter怎么写,大家可以百度一下。
  第二种办法仍然是广播,不过这就需要修改SDK了,在WindManagerService里面,分发按键事件的时候的发送特殊的广播的,这个改动可能比较麻烦。
  第三种办法是直接读取输入设备文件,一般该文件位于/dev/input/文件夹下面,不过里面一般有多个文件,具体哪个文件描述的哪一个输入设备,需要大家进行尝试。设备的文件的读取需要使用c或者c++来完成。具体的实现代码可以参考:https://github.com/radhoo/android-event-injector。这种办法需要有root权限才行,而且读取的键值是没有做过转换的,也就是说和我们平常使用的键值是不一样的。其实大家可以在adb shell中,通过getevent查看。
  第四种办法是使用系统的无障碍服务,也就是AccessibilityService。我最终采用的方式就是这个,因为这个不仅可以监听按键,还能拦截。关于AccessibilityService的实现,网上讲的比较多了。我这里只提几个需要注意的点:
  1、按键拦截需要覆写onKeyEvent方法
  2、AndroidManifest.xml文件中配置如下:

<service
    android:name="your service name"
    android:enabled="true"
    android:exported="true"
    android:permission=
                    "android.permission.BIND_ACCESSIBILITY_SERVICE" >
    <intent-filter>
        <action android:name=
        "android.accessibilityservice.AccessibilityService" />intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibilityservice" />
 service>

  3、在res下面建立一个xml文件夹,然后添加一个xml用于AndroidMenifest引用,xml文件这样写(android:accessibilityFlags不能使用默认的,android:canRequestFilterKeyEvents必须为true,默认的是false): 


<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagRequestFilterKeyEvents"
    android:canRetrieveWindowContent="true"
    android:canRequestFilterKeyEvents="true"
    android:description="@string/app_name">
accessibility-service>

  4、这种方法有个缺陷,该服务是需要用户手动开启的。不过因为我是做自己公司的盒子,所以我可以轻松的成为系统应用,然后自己开启这个服务。开启方法如下:

//注意 这里可能为空(也就是如果当前没有任何一个无障碍服务被授权的时候 就为空了  感谢评论里面指出bug的同学)
String enabledServicesSetting = Settings.Secure.getString(
                getContentResolver(),               Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);

        ComponentName selfComponentName = new ComponentName(getPackageName(),
                "Your AccessibilityService Class Name");
        String flattenToString = selfComponentName.flattenToString();
        if (enabledServicesSetting==null||
            !enabledServicesSetting.contains(flattenToString)) {
            enabledServicesSetting += flattenToString;
        }
        Settings.Secure.putString(getContentResolver(),
                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
                enabledServicesSetting);
        Settings.Secure.putInt(getContentResolver(),
                Settings.Secure.ACCESSIBILITY_ENABLED, 1);

你可能感兴趣的:(Android知识,android,service,监听按键)