模擬Android導航欄三大金剛按鍵點選
模擬Android導航欄三大金剛按鍵點選
這裡需要使用的是AccessibilityService
無障礙輔助服務,可以全域性監聽介面所有的變化;
1.構建無障礙服務
public class FloatService extends AccessibilityService { private static AccessibilityService service; public FloatService() { service = this; } @Override public void onAccessibilityEvent(AccessibilityEvent event) { } @Override public void onInterrupt() { } public static AccessibilityService getService() { if (service==null){ return null; } return service; } }
最基本的繼承操作,加入一個外部可以獲取到Service的方法;
2.宣告服務
我們在Manifest中進行服務宣告:
<service android:name=".Rxjava.FloatService" 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>
這裡注意到我們需要通過meta-data
進行服務配置;
3.配置服務
在\res\xml
中我們設定配置檔案accessibilityservice.xml
:
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityFeedbackType="feedbackGeneric" android:description="@string/accessibility" />
當然這裡我們還可以設定其他的監聽許可權:
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged|typeWindowContentChanged" android:accessibilityFlags="flagDefault" android:canRetrieveWindowContent="true" android:notificationTimeout="100" android:accessibilityFeedbackType="feedbackGeneric" android:description="@string/accessibility" />
這裡解釋一下每個配置項的含義:
-
accessibilityEventTypes
:表示該服務對介面中那些變化感興趣:視窗開啟、滑動、焦點變化、長按等,如typeAllMask
表示接受所有的事件通知; -
accessibilityFeedbackType
:表示反饋方式,比如語音播放,還是震動 -
canRetrieveWindowContent
:表示該服務是否能夠訪問視窗的內容,如果你需要在服務中獲取窗體內容的變化,那麼就需要設定為true了; -
notificationTimeout
:接受事件的時間間隔,一般設定為100ms; -
pacgageNames
:表示服務使用來監聽那個包產生的事件
所以在僅僅只需要使用無障礙服務最基本呼叫全域性BACK、HOME、RECENT的功能,並不需要額外註冊如此多的監控許可權
4.模擬導航欄點選事件
要使用模擬全域性按鍵,我們需要使用到無障礙服務的performGlobalAction(AccessibilityService service)
方法,這個表示執行全域性操作,比如返回,回到主頁,開啟最近操作等;
程式碼如下:
/** * 模擬全域性按鍵 * * @param service */ public static void recentApps(AccessibilityService service,int action) { if (Build.VERSION.SDK_INT < 16) { Toast.makeText(service, "Android 4.1及以上系統才支援此功能,請升級後重試", Toast.LENGTH_SHORT).show(); } else { service.performGlobalAction(action); } }
這裡加入了版本判斷,沒毛病。至於按鍵的action
值,都封裝在了AccessibilityService
中:
recentApps(FloatService.getService(),AccessibilityService.GLOBAL_ACTION_BACK); recentApps(FloatService.getService(),AccessibilityService.GLOBAL_ACTION_HOME); recentApps(FloatService.getService(),AccessibilityService.GLOBAL_ACTION_RECENTS);
還有一些按鍵也都很簡單,不多說了。
5.啟動服務
應用配置完成後需要手動開啟無障礙服務,安裝成功後在設定->輔助功能中就可以找到服務
6.判斷服務是否開啟
當然在正常的使用中我們需要判斷服務是否開啟,以及未開啟時提醒使用者進行處理,類似於許可權處理:
/** * 判斷是否存在置頂的無障礙服務 * @param name * @return */ public boolean isAccessibilityServiceRunning(String name){ AccessibilityManager am= (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE); List<AccessibilityServiceInfo> enableServices = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC); for (AccessibilityServiceInfo enableService : enableServices) { Log.i(TAG, "installService.id-->"+enableService.getId()); if (enableService.getId().endsWith(name)){ return true; } } return false; }
跳轉到無障礙服務設定介面:
startActivity(new Intent("android.settings.ACCESSIBILITY_SETTINGS"));