Android AccessibilityService(輔助服務) 使用示例


1、前言

網上關於Android輔助服務的使用方式已經非常豐富了,所以也不在乎再多我這一篇了:-D。有同學說這是重復造輪子,題主很同意,但反過來說,如果自己沒有能力造出輪子,還對重復造輪子嗤之以鼻,那……,再者,題主認為,自己重復一遍別人的輪子,踩踩坑,要比只看別人的輪子在理解上深刻的多,再不濟,記錄下來權當筆記吧

2、實現步驟

1、自定義服務繼承系統的AccessibilityService服務,重寫必要方法

2、配置AndroidManiFest.xml,增加服務相關配置

3、在res下新建文件夾xml,新建xml文件,配置服務的相關配置,並在AndroidManifest.xml指定該配置文件(也可以在服務類的onServiceConnected中配置)

4、打包、安裝apk,在“設置里”找到輔助服務並開啟即可。

3、具體實現

1、自定義服務,必須實現的方法是onAccessibilityEvent(AccessibilityEvent event)和onInterrupt(),代碼如下

public class AccessibilityServiceTest extends AccessibilityService {

    //可在此方法中配置服務的相關配置,代替配置文件的方式
    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        Log.d("XLZH:", "OnServiceConnected");
    }
    
    //監聽事件類型,根據事件類型不同做不同的處理。事件類型較多,各位可以打印出來篩選出來自己要監聽的事件類型
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        Log.d("XLZH:", event.toString());
        int eventType = event.getEventType();
        switch (eventType) {
            case AccessibilityEvent.TYPE_VIEW_SCROLLED:
                //獲取發生該事件的頁面根view
                AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
                //根據id查找需要點擊的節點,返回的是一個List
                List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("com.tendcloud.demo:id/pager");
                //獲取List的第一個節點,並打印該節點的child數目及類名
                AccessibilityNodeInfo contentNodeInfo = list.get(0);
                Log.d("XLZH size:", String.valueOf(contentNodeInfo.getChildCount()));
                Log.d("XLZH class: ", String.valueOf(contentNodeInfo.getClassName()));

                //通過查找文本的方式獲得節點  
if(contentNodeInfo.findAccessibilityNodeInfosByText("button_test1") != null){
Log.d("XLZH :", "first page"); } if(contentNodeInfo.findAccessibilityNodeInfosByText("button1") != null){ Log.d("XLZH :", "second page"); } if(contentNodeInfo.findAccessibilityNodeInfosByText("tvweb") != null){ Log.d("XLZH :", "third page"); } break; } } @Override public void onInterrupt() { } }

2、配置AndroidManiFest.xml。如下

        <service
            android:name=".AccessibilityServiceTest"
            android:label="AccessibilityServiceTest"
            <!--聲明權限,而不是申請權限-->            
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" android:exported="false">
<intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <!--配置服務服務配置文件路徑--> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_xml" /> </service>

3、編寫輔助服務的配置文件

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/description"          //在設置中顯示的內容
    android:accessibilityEventTypes="typeAllMask"   //監聽事件的類型
    android:accessibilityFeedbackType="feedbackGeneric" //反饋的類型
    android:notificationTimeout="100"                    //設置超時時間
    android:accessibilityFlags="flagDefault"             //配置flag
    android:canRetrieveWindowContent="true"        //可以獲取窗口上的對象的值
    android:packageNames="com.tendcloud.demo" /> //配置要監聽的包名

4、其他

1、有個印象深刻的坑是在配置AndroidManifest.xml時,不是使用<user-permission ...>,而是要在Service里聲明服務,即有BIND_ACCESSIBILITY_SERVICE的應用才能訪問該服務,而不是該服務需要申請這個權限

2、本來想是否可以只要該Service,而不要Activity,經過查閱資料、親自嘗試,結果是……不行!

3、還有一個坑,至今沒有解決。測試的目的apk界面, 如下

如代碼所示,本來想通過查找控件確定當前是那個頁面,測試結果發現當在第一個頁面的時候,Child包括第二個頁面中的控件,當在第二個頁面的時候,Child包括第一個、第二、第三個頁面中的控件,當在第三個頁面的時候,Child包括第二個頁面和第三個頁面中的控件。

具體原因不明白,有大神可以測試並指導一下,謝謝。

測試對象apk

測試代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM