如何使用 AccessibilityService 在 Android Oreo 和更高版本中点击 UI window?
How click in UI window on Android Oreo and higher with AccessibilityService?
我已经按照 this 的建议以编程方式卸载我的应用程序并且在 Android 7.1 之前一切正常,但是当我在 Android 8.1 和 9 上测试相同时,这似乎不工作(none 点击 Ui window)。发生了什么?在这些版本中对此进行了一些更新?
主要代码>
我的辅助功能:
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if (source == null) {
return;
}
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
List<AccessibilityNodeInfo> list = source.findAccessibilityNodeInfosByViewId("android:id/button1");
for (AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
XML(主要):
<service
android:name=".MyAccessibility"
class=".MyAccessibility"
android:enabled="true"
android:exported="false"
android:label="@string/accessibility_service_label"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action
android:name=".MyAccessibility"
android:value=".MyAccessibility" />
</intent-filter>
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config" />
</service>
XML(无障碍服务):
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagReportViewIds"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_service_description"
android:notificationTimeout="100"
tools:ignore="UnusedAttribute" />
编辑:
测试环境:
- 摩托罗拉 G5(S) Plus - Android 7.1 和 8.1(更新)
- 摩托罗拉 G7 Plus - Android 9.0
我做了一些测试,发现在 Android 8 及更高版本上尝试卸载应用程序时,AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
事件会触发,但 AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
事件不会触发。此外,当您对 AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
类型的事件调用 AccessibilityEvent.getSource()
方法时,它 returns 为空。所以我在 AccessibilityEvent.getSource()
方法 returns null 时使用 getRootInActiveWindow()
方法,此外在 API 26 及更高版本上,我也尝试处理 AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
事件。
请试试这个代码:
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && source == null)
source = getRootInActiveWindow();
if (source == null) {
return;
}
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
List<AccessibilityNodeInfo> list = source.findAccessibilityNodeInfosByViewId("android:id/button1");
for (AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
我也修改了 accessibility_service_config.xml
文件以提高准确性。
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackAllMask"
android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagReportViewIds"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_service_description"
android:notificationTimeout="100"
tools:ignore="UnusedAttribute"
android:packageNames="com.google.android.packageinstaller, com.android.packageinstaller"/>
我已经在 API 24、API 27、API 28 和 API 29 上测试了这段代码,并且有效。
我已经按照 this 的建议以编程方式卸载我的应用程序并且在 Android 7.1 之前一切正常,但是当我在 Android 8.1 和 9 上测试相同时,这似乎不工作(none 点击 Ui window)。发生了什么?在这些版本中对此进行了一些更新?
主要代码>
我的辅助功能:
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if (source == null) {
return;
}
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
List<AccessibilityNodeInfo> list = source.findAccessibilityNodeInfosByViewId("android:id/button1");
for (AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
XML(主要):
<service
android:name=".MyAccessibility"
class=".MyAccessibility"
android:enabled="true"
android:exported="false"
android:label="@string/accessibility_service_label"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action
android:name=".MyAccessibility"
android:value=".MyAccessibility" />
</intent-filter>
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config" />
</service>
XML(无障碍服务):
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagReportViewIds"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_service_description"
android:notificationTimeout="100"
tools:ignore="UnusedAttribute" />
编辑:
测试环境:
- 摩托罗拉 G5(S) Plus - Android 7.1 和 8.1(更新)
- 摩托罗拉 G7 Plus - Android 9.0
我做了一些测试,发现在 Android 8 及更高版本上尝试卸载应用程序时,AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
事件会触发,但 AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
事件不会触发。此外,当您对 AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
类型的事件调用 AccessibilityEvent.getSource()
方法时,它 returns 为空。所以我在 AccessibilityEvent.getSource()
方法 returns null 时使用 getRootInActiveWindow()
方法,此外在 API 26 及更高版本上,我也尝试处理 AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
事件。
请试试这个代码:
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo source = event.getSource();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && source == null)
source = getRootInActiveWindow();
if (source == null) {
return;
}
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED || Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
List<AccessibilityNodeInfo> list = source.findAccessibilityNodeInfosByViewId("android:id/button1");
for (AccessibilityNodeInfo node : list) {
node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
我也修改了 accessibility_service_config.xml
文件以提高准确性。
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackAllMask"
android:accessibilityFlags="flagDefault|flagIncludeNotImportantViews|flagReportViewIds"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_service_description"
android:notificationTimeout="100"
tools:ignore="UnusedAttribute"
android:packageNames="com.google.android.packageinstaller, com.android.packageinstaller"/>
我已经在 API 24、API 27、API 28 和 API 29 上测试了这段代码,并且有效。