アクセシビリティビューの階層をいつでもアクセシビリティサービスから任意に検索できます。いくつかのタイプのアクセシビリティイベントの文脈の中からそうすることをお勧めしますが、あなたが通過するスクリーンコンテンツがあることを確認してください!無作為なコールバックでそうすることはせいぜい気をつけているだけです。ここでは、合理的なアクセシビリティ設定XMLファイルは、このような目的のために使用することです:
以下
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/accessibility_service_description"
android:accessibilityEventTypes="typeWindowContentChanged|typeWindowsChanged|typeWindowStateChanged"
android:accessibilityFlags="flagReportViewIds|flagIncludeNotImportantViews"
android:canRetrieveWindowContent="true"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="1000"
android:settingsActivity=".SettingsActivity"
/>
は、具体的には、これらのフィールドのいくつかのいくつかのコメントです。
アンドロイド:notificationTimeout = "1000"
だけ1秒に1回与えられたタイプのアクセシビリティイベントを取得!イベントがリストされている場合、より低い設定はQUERVERBOSEです。コールバックを呼び出し、ノードがあることを確認するために、これに頼っています。 1秒に1回、これらの目的のためにちょうどいいです。必要に応じて微調整します。
アンドロイド:accessibilityEventTypes = "typeWindowContentChanged | typeWindowsChanged | typeWindowStateChanged"
は、大まかに言えば、これはあなたがすべての画面変更イベントをキャッチすることができますイベントのサブセットです。新しいウィンドウを開く...ビュー階層をスキャンする!
アンドロイド:accessibilityFlags = "flagReportViewIds | flagIncludeNotImportantViews"
旗はない重要なビューがAccessibilityNodeInfoの階層構造でより多くの景色を眺めることができます含まれています。具体的には多くのレイアウトビューがあり、Android OSは通常、アクセシビリティの目的では必要と思われません。私はこれをチェックしたままにしておきます。これは開発者が調整可能なプロパティでもあり、Android開発者はアクセシビリティに関しては馬鹿げたことに悪名高いです。すべてを取って自分で分類するのがベストです!
あなたのサービス設定があります。今、残りはとても簡単です。あなたがしたいことは、TextViewノードが見つかるまで、ルートノードの子を再帰させることです。私は上記のサービス設定のXMLを与えられた後、毎秒1回以上来ない限り、各画面の最初のTextViewノードが更新され、スクリーン座標を記録するという愚かなサービスを設定しました。
class MyAccessibilityService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent e) {
//You can actually call getRootInActiveWindow() any time!
//Doing so here ensures that the screen is in a reasonable state
//and not in the middle of rendering or something else silly.
final AccessibilityNodeInfo textNodeInfo = findTextViewNode(getRootInActiveWindow());
if (textNodeInfo == null) return;
Rect rect = new Rect();
textNodeInfo.getBoundsInScreen(rect);
Log.i(A11yService.class.getSimpleName(), "The TextView Node: " + rect.toString());
}
public AccessibilityNodeInfo findTextViewNode(AccessibilityNodeInfo nodeInfo) {
//I highly recommend leaving this line in! You never know when the screen content will
//invalidate a node you're about to work on, or when a parents child will suddenly be gone!
//Not doing this safety check is very dangerous!
if (nodeInfo == null) return null;
Log.v(A11yService.class.getSimpleName(), nodeInfo.toString());
//Notice that we're searching for the TextView's simple name!
//This allows us to find AppCompat versions of TextView as well
//as 3rd party devs well names subclasses... though with perhaps
//a few poorly named unintended stragglers!
if (nodeInfo.getClassName().toString().contains(TextView.class.getSimpleName())) {
return nodeInfo;
}
//Do other work!
for (int i = 0; i < nodeInfo.getChildCount(); i++) {
AccessibilityNodeInfo result = findTextViewNode(nodeInfo.getChild(i));
if (result != null) return result;
}
return null;
}
//Required for a valid Accessibility Service.
@Override
public void onInterrupt() {}
}
ます。また、このもののすべてがはるかに容易になり、私はAccessibility Service Utilitiesで作られたオープンソースのライブラリを、探し出すことができます! A11yNodeInfoMatcherクラスはあなたが望むものです。