Android Accessibility輔助功能類的學習


AccessibilityService是一個輔助類,可以監聽我們手機的焦點,窗口變化,按鈕點擊等等。實現它的服務需要在手機設置里面->輔助功能在這里面找到你自己實現的輔助類,然后打開它就可以進行我們一系列的監聽,這個功能google的出發點是給那些肢體上有障礙的人使用的,比如手指不健全的用戶,怎么才能滑動屏幕,然后打開一個應用呢?那么輔助功能就是干這些事,他的功能其實就是可以概括兩句話:

第一、尋找到我們想要的View節點

第二、然后模擬點擊,實現特定功能

我們知道Android中的View體系是一個樹形結構,那么每一個View就是一個節點。所以我們可以查找到指定的節點,那么我們該如何查找到我們想要的節點呢?這里我們先看一下輔助功能(AccessibilityService)的用法。

第一步、我們需要集成AccessibilityService類

我們需要自定一個Service然后繼承AccessibilityService,當然還需要在AndroidManifest.xml中聲明這個服務:

<application>  
  <service android:name=".MyAccessibilityService"  
      android:label="@string/accessibility_service_label">  
    <intent-filter>  
      <action android:name="android.accessibilityservice.AccessibilityService" />  
    </intent-filter>
    <mate-data
     android:name="android.accessibilityservice"
     anroid:resource="@xml/accessibility"/>
  </service>  
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />  
</application>

在<application>標簽下添加指定了AccessibilityService的子類MyAccessibilityService,同時加入相應的權限。

<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" /> 

當然還要一個meta-data的聲明,這個聲明是對這個AccessibilityService的配置。我們看一下配置文件內容:

(注:從Android4.0開始,開發者可以通過在AndroidManifest里添加<meta-data>標簽,在標簽里指出配置文件的位置)

<?xml version="1.0" encoding="utf-8"?>  
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"  
    android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged"  
    android:accessibilityFeedbackType="feedbackGeneric"  
   android:accessibilityFlags="flagDefault"  
    android:canRetrieveWindowContent="true"  
    android:description="@string/desc"  
    android:notificationTimeout="100"  
    android:packageNames="com.tencent.mm" />  

這里我們看到有很多選項,我們看一下常用的幾個屬性:

1、android:accessibilityEventTypes="typeAllMask"
看屬性名也差不多可以明白,這個是用來設置響應事件的類型,typeAllMask當然就是響應所有類型的事件了。當然還有單擊、長按、滑動等。

2、android:accessibilityFeedbackType="feedbackSpoken"
設置回饋給用戶的方式,有語音播出和振動。可以配置一些TTS引擎,讓它實現發音。

3、android:notificationTimeout="100"
響應時間的設置就不用多說了

4、android:packageNames="com.example.android.apis"
可以指定響應某個應用的事件,這里因為要響應所有應用的事件,所以不填,默認就是響應所有應用的事件。比如我們寫一個微信搶紅包的輔助程序,就可以在這里填寫微信的包名,便可以監聽微信產生的事件了。
我們這些配置信息除了在xml中定義,同樣也可以在代碼中定義,我們一般都是在onServiceConnected()方法里進行

@Override  
protected void onServiceConnected() {  
    AccessibilityServiceInfo info = getServiceInfo();  
    info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;  
    info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;    
    info.notificationTimeout = 100;    
    setServiceInfo(info);   
    info.packageNames = new String[]{"xxx.xxx.xxx", "yyy.yyy.yyy","...."};  
    setServiceInfo(info);  
    super.onServiceConnected();  
}  

在子類MyAccessibilityService里實現幾個重要的重載方法:
         onServiceConnected() - 可選。系統會在成功連接上你的服務的時候調用這個方法,在這個方法里你可以做一下初始化工作,例如設備的聲音震動管理,也可以調用setServiceInfo()進行配置工作。
         onAccessibilityEvent() - 必須。通過這個函數可以接收系統發送來的AccessibilityEvent,接收來的AccessibilityEvent是經過過濾的,過濾是在配置工作時設置的。
         onInterrupt() - 必須。這個在系統想要中斷AccessibilityService返給的響應時會調用。在整個生命周期里會被調用多次。

         onUnbind() - 可選。在系統將要關閉這個AccessibilityService會被調用。在這個方法中進行一些釋放資源的工作。

2、這里我們一般都會在這里寫上我們需要監聽的應用的包名,但是有時候我們需要監聽多個應用,那么這時候我們該怎么辦呢?

第一種:我們在代碼中注冊多個應用的包名,從而可以監聽多個應用:

 

@Override  
protected void onServiceConnected() {  
    AccessibilityServiceInfo info = getServiceInfo();  
    //這里可以設置多個包名,監聽多個應用  
    info.packageNames = new String[]{"xxx.xxx.xxx", "yyy.yyy.yyy","...."};  
    setServiceInfo(info);  
    super.onServiceConnected();  
} 

 

第二種:我們在onAccessibilityEvent事件監聽的方法中做包名的過濾(這種方式最常用)

@Override  
public void onAccessibilityEvent(AccessibilityEvent event) {  
    String pkgName = event.getPackageName().toString();  
    if("xxx.xxx.xxx".equals(pkgName)){  
  
    }else if("yyy.yyy.yyy".equals(pkgName)){  
  
    }else if("....".equals(pkgName)){  
  
    }  
} 

第三步、在onAccessibilityEvent方法中監聽指定的事件

這里面最重要的部分就是onAccessibilityEvent這個回調函數,當我們注冊了監聽事件的時候,當有事件發生就會通知我們這個函數,但是一定要注意這個函數通知是異步的,當然很多朋友就會問這個是怎么通知到這里來的呢?他是通過AccessibilityDelegate這個代理類,發送出來的,這個類有個方法sendAccessibilityEvent可以發送事件。那這個類又怎么和我們的窗口聯系呢?這里舉個例子。比如我們的View類里面有個setAccessibilityDelegate這個方法,是不是這下一切都明了了呢?然后就是調用我們的find函數去當前節點里面找到我們需要的節點信息。

@Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        switch (eventType) {
        case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
            //.......
        }
}

這個事件類型很多的,我們可以查看AccessibilityEvent類的源碼

 

第四步、查找到我們想要處理的節點View

這里系統提供了兩個方法讓我們來進行查找想要的節點View

第一種是通過節點View的Text內容來查找

findAccessibilityNodeInfosByText("查找內容")

這種方式查找,就是像TextView,Button等View有文本內容的,可以使用這種方式快速的找到。

第二種是通過節點View在xml布局中的id名稱

findAccessibilityNodeInfosByViewId("@id/xxx")

這個一般很難知道,但是我們在查找系統控件的時候還是可以做的,因為系統的控件的id是可以知道的,而且是統一的。
(關於這兩個方法我們在寫網頁爬蟲程序的時候可能知道,在html中通過tag/name/id等信息可以找到一個節點,原理都類似)

 

第五步、模擬點擊指定事件

 

我們找到我們想要的View節點,調用方法模擬事件:

 

performAction(AccessibilityNodeInfo.ACTION_CLICK)

 

調用這個方法即可,當然這里的參數就是指定事件的名稱,這個和AccessibilityEvent中監聽的那些事件是一一對應的,這里是模擬點擊事件,我們當然可以模擬View的滾動事件,長按事件等。

 


免責聲明!

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



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