多くの Android ユーザーは、さまざまな状況でさまざまな方法で携帯電話を操作することになります。視覚、聴覚、またはその他の身体的な理由により Android スマートフォンを使用できないユーザーのために、Android は、テキスト読み上げ、触覚フィードバック、ジェスチャー操作、トラックボールなど、ユーザーがデバイスをより簡単に操作できるようにするアクセシビリティ機能とサービスを提供します。そしてハンドル操作。開発者は、音声プロンプト、物理的フィードバック、その他のオプションの動作モードなど、アプリケーションの使いやすさを向上させる独自のアクセシビリティ サービスを構築できます。
その具体的な実装は、AccessibilityService サービスを通じてバックグラウンドで実行し、AccessibilityEvent を通じて指定されたイベントのコールバックを受信することです。このようなイベントは、フォーカスが変更された、ボタンがクリックされたなど、インターフェイス内のユーザーによるいくつかの状態遷移を表します。このようなサービスには、アクティブなウィンドウのコンテンツを要求する機能がオプションで備わっている場合があります。簡単に言えば、AccessibilityService はバックグラウンド監視サービスであり、監視するコンテンツが変化すると、バックグラウンド サービスのコールバック メソッドが呼び出されます。
独自の Service クラスを作成し、onServiceConnected() メソッド、onAccessibilityEvent() メソッド、および onInterrupt() メソッドをオーバーライドします。
public class QHBAccessibilityService extends AccessibilityService {
/**
* 当启动服务的时候就会被调用
*/
@ Override
protected void onServiceConnected () {
super . onServiceConnected ();
}
/**
* 监听窗口变化的回调
*/
@ Override
public void onAccessibilityEvent ( AccessibilityEvent event ) {
int eventType = event . getEventType ();
//根据事件回调类型进行处理
}
/**
* 中断服务的回调
*/
@ Override
public void onInterrupt () {
}
}
以下は、AccessibilityService で一般的に使用されるメソッドの紹介です。
バックグラウンドサービスであるため、マニフェストでサービス情報を構成する必要があります
< service
android : name = " .AccessibilityService.QHBAccessibilityService "
android : enabled = " true "
android : exported = " true "
android : label = " @string/label "
android : permission = " android.permission.BIND_ACCESSIBILITY_SERVICE " >
< intent-filter >
< action android : name = " android.accessibilityservice.AccessibilityService " />
</ intent-filter >
</ service >
注意が必要です。情報設定に誤りがあると、サービスが応答しなくなります。
サービス パラメータの設定とは、指定されたタイプのイベントの受け入れ、指定されたパッケージのリッスン、ウィンドウ コンテンツの取得、イベント タイプの時刻の取得などの設定を指します。サービスパラメータを設定するには 2 つの方法があります。
元のマニフェストにメタデータ タグを追加して XML ファイルを指定します
< service
android : name = " .AccessibilityService.QHBAccessibilityService "
android : enabled = " true "
android : exported = " true "
android : label = " @string/label "
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/accessibility_service_config " />
</ service >
次に、accessibility_service_config ファイルの構成です。
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< accessibility-service xmlns : android = " http://schemas.android.com/apk/res/android "
android : accessibilityEventTypes = " typeNotificationStateChanged|typeWindowStateChanged|typeWindowContentChanged|typeWindowsChanged "
android : accessibilityFeedbackType = " feedbackGeneric "
android : accessibilityFlags = " flagDefault "
android : canRetrieveWindowContent = " true "
android : description = " @string/description "
android : notificationTimeout = " 100 "
android : packageNames = " com.tencent.mm " />
以下は XML パラメーターの概要です。
accessibilityEventTypes: サービスがインターフェイスのどの変更に関心があるかを示します。つまり、ウィンドウを開く、スライドする、フォーカス変更、長押しなど、どのイベントが通知されるかを示します。特定の値は AccessibilityEvent クラスにあります。たとえば、typeAllMask はすべてのイベント通知を受け入れることを意味します。
accessibilityFeedbackType: 音声再生や振動などのフィードバック方法を示します。
canRetrieveWindowContent: サービスがアクティブ ウィンドウのコンテンツにアクセスできるかどうかを示します。つまり、サービス内のフォームのコンテンツを取得したい場合は、その値を true に設定する必要があります。
description: 以下の図に示すように、アクセシビリティ機能の説明。
notificationTimeout: イベントを受け入れる時間間隔。通常は 100 に設定されます。
packageNames: イベントの監視にサービスが使用されるパッケージを示します。ここでは例として WeChat のパッケージ名を取り上げます。
コードを通じて AccessibilityService の AccessibilityServiceInfo 情報を設定するためのメソッドに抽出できます。
private void settingAccessibilityInfo () {
String [] packageNames = { "com.tencent.mm" };
AccessibilityServiceInfo mAccessibilityServiceInfo = new AccessibilityServiceInfo ();
// 响应事件的类型,这里是全部的响应事件(长按,单击,滑动等)
mAccessibilityServiceInfo . eventTypes = AccessibilityEvent . TYPES_ALL_MASK ;
// 反馈给用户的类型,这里是语音提示
mAccessibilityServiceInfo . feedbackType = AccessibilityServiceInfo . FEEDBACK_SPOKEN ;
// 过滤的包名
mAccessibilityServiceInfo . packageNames = packageNames ;
setServiceInfo ( mAccessibilityServiceInfo );
}
AccessibilityServiceInfo クラスは、AccessibilityService 情報を構成するために使用されます。このクラスには、accessibilityEventTypes、canRequestFilterKeyEvents、packageNames などの構成および XML 属性用の多数の定数フィールドが含まれています。
ここでは、アクセシビリティ機能でこの機能を手動でオンにする必要があります。そうしないと、続行できません。次のコードを使用して、システムのアクセシビリティ機能リストを開くことができます。
Intent intent = new Intent ( Settings . ACTION_ACCESSIBILITY_SETTINGS );
startActivity ( intent );
イベントの通知バーとインターフェイスを監視しているため、指定された packageNames の通知バーまたはインターフェイスが変更されると、イベントが onAccessibilityEvent を通じてコールバックされ、その後イベントが処理されます。
@ Override
public void onAccessibilityEvent ( AccessibilityEvent event ) {
int eventType = event . getEventType ();
//根据事件回调类型进行处理
switch ( eventType ) {
//当通知栏发生改变时
case AccessibilityEvent . TYPE_NOTIFICATION_STATE_CHANGED :
break ;
//当窗口的状态发生改变时
case AccessibilityEvent . TYPE_WINDOW_STATE_CHANGED :
break ;
}
}
WeChat で通知を受け取ると、プッシュ メッセージがステータス バーに到着します。このとき、それは TYPE_NOTIFICATION_STATE_CHANGED によって監視され、WeChat インターフェイスを切り替えるか、WeChat を使用すると、その中のコンテンツが実行されます。 TYPE_WINDOW_STATE_CHANGED によって監視されます。内部のコンテンツを実行します。
AccessibilityEvent メソッド
インターフェースウィンドウの変更を取得した後、この時点で制御ノードを取得する必要があります。ウィンドウ全体のノードは基本的にツリー構造になっており、ノード情報は以下のように操作されます。
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow ();
//通过文本找到对应的节点集合
List < AccessibilityNodeInfo > list = nodeInfo . findAccessibilityNodeInfosByText ( text );
//通过控件ID找到对应的节点集合,如com.tencent.mm:id/gd
List < AccessibilityNodeInfo > list = nodeInfo . findAccessibilityNodeInfosByViewId ( clickId );
ノード情報を取得した後、コントロール ノード上でクリック、長押し、その他の操作をシミュレートできます。AccessibilityNodeInfo クラスには、シミュレートされた操作を実行できるメソッドが用意されています。詳細については、公式ドキュメントを参照してください。一般的な操作はここにリストされています。
//模拟点击
accessibilityNodeInfo . performAction ( AccessibilityNodeInfo . ACTION_CLICK );
//模拟长按
accessibilityNodeInfo . performAction ( AccessibilityNodeInfo . ACTION_LONG_CLICK );
//模拟获取焦点
accessibilityNodeInfo . performAction ( AccessibilityNodeInfo . ACTION_FOCUS );
//模拟粘贴
accessibilityNodeInfo . performAction ( AccessibilityNodeInfo . ACTION_PASTE );
携帯電話が USB ケーブルに接続されたら、Android Device Monitor でデバイスを選択し、UI Automator ツールの Dump View Hierarchy を開きます。これを通じて制御情報を取得できます。
Q:
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
ブロガーはこの問題に遭遇しましたか?私もあなたのような問題に遭遇しました。それは「構成サービスパラメータ」にあると思いますが、これも android:canRetrieveWindowContent="true" と書いていないような気がします。 , しかし、そうではありませんでした。android:canRetrieveWindowContent="true" に対応する設定を見つけたので、それを xml で構成するように変更したところ、問題ありませんでした。
Q: これらのクラス名 com.tencent.mm.ui.LauncherUI はどのように取得しますか? A: String className =event.getClassName().toString(); ログを使用して出力し、WeChat を開いてログ情報を表示します。
原文:Hensen_のブログ