AndroidアクセシビリティサービスAccessibilityService

7551 ワード

転載先:http://www.jianshu.com/p/27df6983321f
Androidが補助機能サービスを提供する目的は、視覚、身体、または年齢に関する制限を有するユーザが、画面の重要な領域にユーザがぶら下がっているときにテキストを音声または触覚フィードバックに変換し、視力に欠陥のあるユーザも使用できるように、Androidデバイスおよびアプリケーションをより容易に使用できるようにすることである.このほか、AccessibilityServiceを使用して手動操作を自動化し、退屈で煩雑な繰り返し操作から解放することもできます.
1.まず、AccessibilityServiceから継承されたサービス(ここではMyAccessibilityServiceと命名)を定義し、AndroidManifestで宣言する必要があります.

    
        
    

    

このうちaccessibility_service_descriptionはこのサービスに関する機能説明であり、accessibility_service_labelはサービスの名称であり、これらは設置中の補助サービスに表示され、ユーザーは中でサービスを開く必要がある.permissionintent-filterは固定表記です.meta-dataは主にサービスのいくつかの構成に用いられ、構成の具体的な内容は res/xml/accessibility_service_config.xml ファイル:

サービスのコンフィギュレーション・オプションの詳細は、「」を参照してください. https://developer.android.com/reference/android/accessibilityservice/AccessibilityServiceInfo.html ここでは、android:packageNamesサービスが監視するアプリケーションのパケット名をいくつか説明し、複数ある場合はカンマで接続し、すべてのアプリケーションを監視することを空にします.android:accessibilityEventTypesサービスは、通知、ウィンドウの変更、クリック、フォーカスの変更など、監視するイベントのタイプを監視し、複数の|で接続できる場合、typeAllMaskはすべてのタイプを表します.android:accessibilityFeedbackTypeサービスフィードバックの方式、例えば音声、振動など、feedbackAllMaskはすべてのタイプを表す.android:notificationTimeout  イベントを受信する間隔(ミリ秒)android:canRetrieveWindowContent サービスがウィンドウの内容を取得できるかどうかこれらの構成はxmlに書かれているほか、コードにAccessibilityServiceInfoオブジェクトを作成し、setServiceInfo()で設定することもできます.
2、補助サービスはAccessibilityServiceクラスを継承し、そのクラスを上書きする以下の方法:onServiceConnected システムがアクセシビリティサービスに正常に接続されたときに呼び出され、オーディオマネージャやデバイスバイブレータなどのユーザーフィードバックシステムサービスに接続するなど、任意の使い捨て設定ステップを実行できます.setServiceInfo()を呼び出してサービス構成を設定することもできます.onAccessibilityEvent  システムがAccessibilityサービスによって指定されたイベントフィルタパラメータに一致するAccessibilityEventを検出すると呼び出されます.これは実装されなければならない方法であり、通常、この方法ではAccessibilityEventに基づいて判断し、いくつかの処理を実行する必要がある.onInterrupt  システムがサービス提供のフィードバックを中断したい場合に呼び出されます.通常、フォーカスを他のコントロールに移動するなど、ユーザーの操作に応答します.onUnbindまたはonDestroy システムがアクセシビリティサービスをシャットダウンしようとすると呼び出され、オーディオマネージャやデバイスバイブレータなどのユーザフィードバックシステムサービスの割り当てを解除するなど、任意の使い捨てシャットダウンプログラムを実行することができる.
3、AccessibilityEventは補助機能サービスにおいて非常に重要なクラスであり、主にユーザーインタフェースのインタラクションに関する情報を提供するために使用される.ユーザーインタフェースでサービスが注目すべきイベントが発生すると、システムはAccessibilityEventイベントを送信し、onAccessibilityEventメソッドに渡します.通常、event.getEventType()event.getClassName()が多く用いられ、それぞれ現在のイベントのタイプとそのイベントが発生したクラス名を取得するために用いられ、この2つの判断により処理したいイベントをフィルタリングし、操作することができる.例えば、ボタンをクリックするとtypeがTYPE_と送信されますVIEW_CLICKED、classNameはandroid.widget.Buttonのイベントで、あるボタンがクリックされたときにいくつかの操作をする必要がある場合は、onAccessibilityEventでeventを判断することができます.AccessibilityEventのTypeは次のとおりです.
TYPE_VIEW_CLICKED
TYPE_VIEW_LONG_CLICKED
TYPE_VIEW_FOCUSED
TYPE_VIEW_SELECTED
TYPE_VIEW_TEXT_CHANGED
TYPE_WINDOW_STATE_CHANGED
TYPE_NOTIFICATION_STATE_CHANGED
TYPE_TOUCH_EXPLORATION_GESTURE_START
TYPE_TOUCH_EXPLORATION_GESTURE_END
TYPE_VIEW_HOVER_ENTER
TYPE_VIEW_HOVER_EXIT
TYPE_VIEW_SCROLLED
TYPE_VIEW_TEXT_SELECTION_CHANGED
TYPE_WINDOW_CONTENT_CHANGED
TYPE_ANNOUNCEMENT
TYPE_GESTURE_DETECTION_START
TYPE_GESTURE_DETECTION_END
TYPE_TOUCH_INTERACTION_START
TYPE_TOUCH_INTERACTION_END
TYPE_VIEW_ACCESSIBILITY_FOCUSED
TYPE_WINDOWS_CHANGED
TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED

4、AccessibilityNodeInfoは同様に補助機能サービスにおいて非常に重要なクラスであり、Viewのステータス情報を表している.イベントが発生したコントロールの情報をevent.getSource()で取得したり、現在のウィンドウのルートノードの情報をgetRootInActiveWindow()で取得したりすることができます.サービス構成のandroid:canRetrieveWindowContenttrueであり、イベントが発生したウィンドウが現在のウィンドウであることを前提とします.そうしないと、両方のメソッドが返す値はnullです.では、AccessibilityNodeInfoを手に入れたら何ができるのでしょうか.AccessibilityNodeInfoはViewと同様に階層関係のあるノードツリーでもあり、1つのAccessibilityNodeInfoには複数のAccessibilityNodeInfoのサブノードがあり、1つのターゲットノードを取得したい場合は、ルートノードを取得してから、そのサブノードを再帰的に遍歴することで探すこともでき、findAccessibilityNodeInfosByViewId()findAccessibilityNodeInfosByText()の方法で探すこともできます.ターゲットノードが見つかったら、クリック、スクロール、文字の記入など、目的の操作を実行できます.たとえば、現在のインタフェースで最初の文字が「OK」のボタンをクリックしたい場合:
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
if (rootNode != null) {
    List nodes = rootNode.findAccessibilityNodeInfosByText("  ");
    for (AccessibilityNodeInfo node : nodes) {
        if (TextUtils.equals(node.getText(), "  ") && TextUtils.equals(node.getClassName(), "android.widget.Button")) {
            node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
    }
}

まず、getRootInActiveWindow()を呼び出して現在のインタフェースのルートノードを取得し、その後、findAccessibilityNodeInfosByText()を介してターゲット文字を含むすべてのノードを見つけ(ここではターゲット文字を含むが、完全にターゲット文字と同じではないことに注意)、このリストを巡回して、最初のTextがターゲット文字に完全に等しく、コントロールタイプがButtonのノードを見つけ、最後に、performAction(AccessibilityNodeInfo.ACTION_CLICK)を呼び出してクリックイベントを実行する.AccessibilityNodeInfoのアクションには、次のものがあります.
ACTION_ACCESSIBILITY_FOCUS
ACTION_ARGUMENT_COLUMN_INT
ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN
ACTION_ARGUMENT_HTML_ELEMENT_STRING
ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT
ACTION_ARGUMENT_PROGRESS_VALUE
ACTION_ARGUMENT_ROW_INT
ACTION_ARGUMENT_SELECTION_END_INT
ACTION_ARGUMENT_SELECTION_START_INT
ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE
ACTION_CLEAR_ACCESSIBILITY_FOCUS
ACTION_CLEAR_FOCUS
ACTION_CLEAR_SELECTION
ACTION_CLICK
ACTION_COLLAPSE
ACTION_COPY
ACTION_CUT
ACTION_DISMISS
ACTION_EXPAND
ACTION_FOCUS
ACTION_LONG_CLICK
ACTION_NEXT_AT_MOVEMENT_GRANULARITY
ACTION_NEXT_HTML_ELEMENT
ACTION_PASTE
ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
ACTION_PREVIOUS_HTML_ELEMENT
ACTION_SCROLL_BACKWARD
ACTION_SCROLL_FORWARD
ACTION_SELECT
ACTION_SET_SELECTION
ACTION_SET_TEXT
FOCUS_ACCESSIBILITY
FOCUS_INPUT
MOVEMENT_GRANULARITY_CHARACTER
MOVEMENT_GRANULARITY_LINE
MOVEMENT_GRANULARITY_PAGE
MOVEMENT_GRANULARITY_PARAGRAPH
MOVEMENT_GRANULARITY_WORD

クリック、長押し、スクロールなど、EditTextに文字を設定したい場合は、次のように使用できます.
Bundle arguments = new Bundle();
arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
inputNode.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);

さらに、AccessibilityServiceには、次のような一般的なイベントを実行するためのperformGlobalAction()の方法があります.
GLOBAL_ACTION_BACK          
GLOBAL_ACTION_HOME      home
GLOBAL_ACTION_NOTIFICATIONS        
GLOBAL_ACTION_RECENTS          
GLOBAL_ACTION_QUICK_SETTINGS          
GLOBAL_ACTION_POWER_DIALOG