探討Android實現後臺(Service)按鍵監聽的功能
一般來說需要做這個功能的大多數是機頂盒或者智慧電視,也就是AndroidTv。剛好這兩天公司的機頂盒有這麼一個需求,針對遙控器某些特殊按鍵,實現按鍵的監聽,並實現相應的功能。研究了一下,大概有這麼一些辦法。
第一種辦法是廣播,一般來說系統對於音量鍵和Home鍵會發送廣播,我們可以再廣播中監聽這些按鍵資訊。具體的IntentFilter怎麼寫,大家可以百度一下。
第二種辦法仍然是廣播,不過這就需要修改SDK了,在WindManagerService裡面,分發按鍵事件的時候的傳送特殊的廣播的,這個改動可能比較麻煩。
第三種辦法是直接讀取輸入裝置檔案,一般該檔案位於/dev/input/資料夾下面,不過裡面一般有多個檔案,具體哪個檔案描述的哪一個輸入裝置,需要大家進行嘗試。裝置的檔案的讀取需要使用c或者c++來完成。具體的實現程式碼可以參考:
第四種辦法是使用系統的無障礙服務,也就是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):
<?xml version="1.0" encoding="utf-8"?>
<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);