英文:
Is there a way to click a hyperlink in the a dialog using an AccessibilityService?
问题
我正在尝试使用辅助功能来通过我的应用程序的辅助功能服务点击“在设置中允许”。我查看了AccessibilityNode,但在TextView中没有看到任何可交互的内容。以下是节点的输出:
事件类型:TYPE_WINDOW_CONTENT_CHANGED com.google.android.permissioncontroller android.widget.FrameLayout
来源:
0 | 类名:android.widget.FrameLayout 文本:null 内容描述:null 输入类型 0 操作:ACTION_SELECT、ACTION_CLEAR_SELECTION、ACTION_ACCESSIBILITY_FOCUS、ACTION_SHOW_ON_SCREEN
1 | 类名:android.widget.ScrollView 文本:null 内容描述:null 输入类型 0 操作:ACTION_FOCUS、ACTION_SELECT、ACTION_CLEAR_SELECTION、ACTION_ACCESSIBILITY_FOCUS、ACTION_SHOW_ON_SCREEN
2 | 类名:android.widget.TextView 文本:更改用于应用名称的位置访问? 内容描述:null 输入类型 0 操作:ACTION_SELECT、ACTION_CLEAR_SELECTION、ACTION_ACCESSIBILITY_FOCUS、ACTION_NEXT_AT_MOVEMENT_GRANULARITY、ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY、ACTION_SET_SELECTION、ACTION_SHOW_ON_SCREEN
2 | 类名:android.widget.TextView 文本:此应用希望始终访问您的位置,即使您未使用该应用。在设置中允许。 内容描述:null 输入类型 0 操作:ACTION_FOCUS、ACTION_SELECT、ACTION_CLEAR_SELECTION、ACTION_ACCESSIBILITY_FOCUS、ACTION_NEXT_AT_MOVEMENT_GRANULARITY、ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY、ACTION_SET_SELECTION、ACTION_SHOW_ON_SCREEN
2 | 类名:android.widget.Button 文本:保持“在使用应用程序时” 内容描述:null 输入类型 0 操作:ACTION_FOCUS、ACTION_SELECT、ACTION_CLEAR_SELECTION、ACTION_CLICK、ACTION_ACCESSIBILITY_FOCUS、ACTION_NEXT_AT_MOVEMENT_GRANULARITY、ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY、ACTION_SET_SELECTION、ACTION_SHOW_ON_SCREEN
TextView只有少数可用操作。我已尽力尝试了可用的操作,但未成功。
我还尝试了直接向“设置中允许”部分发送意图,但目前没有任何意图可用。我们的应用程序需要始终开启位置功能。
英文:
I am trying to use Accessibility to click "Allow in settings" using my application's Accessibility Service. I have looked at the AccessibilityNode, and I do not see anything that's interactable in the TextView. Here is the output from the node:
Event Type: TYPE_WINDOW_CONTENT_CHANGED com.google.android.permissioncontroller android.widget.FrameLayout
Source:
0 | class name: android.widget.FrameLayout text: null content description: null input type 0 actions: ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_SHOW_ON_SCREEN
1 | class name: android.widget.ScrollView text: null content description: null input type 0 actions: ACTION_FOCUS, ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_SHOW_ON_SCREEN
2 | class name: android.widget.TextView text: Change location access for AppName? content description: null input type 0 actions: ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ACTION_SET_SELECTION, ACTION_SHOW_ON_SCREEN
2 | class name: android.widget.TextView text: This app wants to access your location all the time, even when you’re not using the app. Allow in settings. content description: null input type 0 actions: ACTION_FOCUS, ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ACTION_SET_SELECTION, ACTION_SHOW_ON_SCREEN
2 | class name: android.widget.Button text: Keep “While the app is in use” content description: null input type 0 actions: ACTION_FOCUS, ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_CLICK, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ACTION_SET_SELECTION, ACTION_SHOW_ON_SCREEN
There are only a handful of available actions for the TextView. I have attempted the available actions to the best of my knowledge with no success.
I have also explored the idea of a direct Intent to the "Allow in Settings" section but at the moment there are none. Our app requires location to be on at all times.
答案1
得分: 1
以下是您要翻译的内容:
因此,我最终所做的是编写了一个用于从CharSequence中获取跨度的静态函数。
@NonNull
ClickableSpan[] getClickableSpans(CharSequence text) {
try {
if (text instanceof Spanned) {
Spanned spanned = (Spanned) text;
return spanned.getSpans(0, text.length(), ClickableSpan.class);
}
} catch (Exception e) {
//记录异常
}
return new ClickableSpan[0];
}
并且在使用时:
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityNodeInfo nodeInfo = event.getSource();
if (nodeInfo != null) {
List<AccessibilityNodeInfo> nodeInfoList = nodeInfo.findAccessibilityNodeInfosByText(
"This app wants to access your location all the time, even when you're not using the app. Allow in settings.");
if (nodeInfoList != null && !nodeInfoList.isEmpty()) {
ClickableSpan[] spans = getClickableSpans(nodeInfoList.get(0).getText());
if (spans.length > 0) {
spans[0].onClick(null);
}
}
}
}
英文:
So what I ended up doing was writing a static function for getting spans from a CharSequence
@NonNull
ClickableSpan[] getClickableSpans(CharSequence text) {
try {
if (text instanceof Spanned) {
Spanned spanned = (Spanned) text;
return spanned.getSpans(0, text.length(), ClickableSpan.class);
}
} catch (Exception e) {
//log exception
}
return new ClickableSpan[0];
}
and to use it
public void onAccessibilityEvent(AccessibilityEvent) {
AccessibilityNodeInfo nodeInfo = event.getSource();
if (nodeInfo != null) {
List<AccessibilityNodeInfo> nodeInfoList = nodeInfo.findAccessibilityNodeInfosByText(
"This app wants to access your location all the time, even when you're not using the app. Allow in settings.");
if (nodeInfoList != null && !nodeInfoList.isEmpty()) {
ClickableSpan[] spans = getClickableSpans(nodeInfoList.get(0).getText());
if (spans.length > 0) {
spans[0].onClick(null);
}
}
}
}
答案2
得分: 0
ClickableSpans 在 Android O 及更高版本中会传递给辅助功能。您可以在文本中找到 ClickableSpans 并调用 onClick 方法。然后系统会确保在应用程序进程中调用原始 span 的 onClick 方法。
如果您使用 AccessibilityNodeInfoCompat,这也会进行向后移植,但是应用程序还必须调用 ViewCompat#enableAccessibleClickableSpanSupport(view)。
英文:
ClickableSpans are passed through to accessibility starting in Android O. You can find the ClickableSpans in the text and call onClick. The system will then make sure the original span's onClick method is called in the app process.
This is back-ported if you use AccessibilityNodeInfoCompat, but the app must also have called ViewCompat#enableAccessibleClickableSpanSupport(view).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论