AccessibilityService 无法从混合 Android 应用程序(即 flutter)读取文本

问题描述 投票:0回答:1

我正在尝试创建一个可从用户屏幕读取文本的 AccessibilityService,它运行良好,并且我能够从本机 Android 应用程序获取大部分文本。不过,当我用我的示例 Flutter 应用程序尝试它时,我得到的所有文本都为空。

这是从我的服务读取文本的当前代码:

private void listAllTextsInActiveWindow() {
    AccessibilityNodeInfo rootNode = getRootInActiveWindow();
    if (rootNode != null) {
        List<HashMap<String, String>> allTexts = new ArrayList<>();
        traverseNodesForText(rootNode, allTexts);
        rootNode.recycle();
        // Now 'allTexts' contains a list of all texts in the active window
        Gson gson = new Gson();
        String json = gson.toJson(allTexts);
        Log.d("OUTPUT", json);
    } else {
        Log.d("OUTPUT", "NULL");
    }
}
private void traverseNodesForText(AccessibilityNodeInfo node, List<HashMap<String, String>> allTexts) {
    if (node == null) return;

    if (node.getText() != null && !node.getText().toString().isEmpty()) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            HashMap data = new HashMap();
            data.put("view_class", node.getClassName());
            data.put("view_text", node.getText());
            data.put("view_description", node.getContentDescription());
            data.put("view_complete_info", node.toString());
            allTexts.add(data);
        }
    }

    for (int i = 0; i < node.getChildCount(); i++) {
        AccessibilityNodeInfo childNode = node.getChild(i);
        traverseNodesForText(childNode, allTexts);
    }
}

我得到一个空数组作为输出。

当我试图让它工作时,我的前辈告诉我有一个名为“Automate”的应用程序,当我尝试使用该应用程序及其 Inspect 布局时,我能够获得包含所有文本的层次结构 XML。

它的输出是:

<hierarchy rotation="0">
    <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.example.apk_installer_demo" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][720,1465]">
        <node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.example.apk_installer_demo" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][720,1465]">
            <node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout" package="com.example.apk_installer_demo" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][720,1465]">
                <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.example.apk_installer_demo" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][720,1465]">
                    <node index="0" text="" resource-id="" class="android.view.View" package="com.example.apk_installer_demo" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][720,1465]">
                        <node index="0" text="" resource-id="" class="android.view.View" package="com.example.apk_installer_demo" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][720,1465]">
                            <node index="0" text="" resource-id="" class="android.view.View" package="com.example.apk_installer_demo" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][720,1465]">
                                <node index="0" text="" resource-id="" class="android.view.View" package="com.example.apk_installer_demo" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][720,1465]">
                                    <node index="0" text="" resource-id="" class="android.view.View" package="com.example.apk_installer_demo" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][720,154]">
                                        <node index="0" text="" resource-id="" class="android.view.View" package="com.example.apk_installer_demo" content-desc="Download & Install Test APK" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[30,75][549,128]"/></node>
                                    <node index="1" text="" resource-id="" class="android.widget.Button" package="com.example.apk_installer_demo" content-desc="Download & Install New Version" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[126,787][594,877]"/></node>
                            </node>
                        </node>
                    </node>
                </node>
            </node>
        </node>
        <node index="1" text="" resource-id="android:id/navigationBarBackground" class="android.view.View" package="com.example.apk_installer_demo" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][0,0]"/></node>
</hierarchy>

现在这个输出是可读的,我正在努力实现这样的目标。

让我知道我是否可以做到这一点。

java android accessibility android-xml accessibilityservice
1个回答
0
投票

使用 uiautomator 转储进行良好调用!您是否注意到所有节点的文本都是空的?我不确定 Flutter 如何处理按钮上的文本可视文本,但您需要检查行中的内容描述 (

content-desc
)

if (node.getText() != null && !node.getText().toString().isEmpty())

否则你会错过它。尝试一下

if (node.getText() != null && (!node.getText().toString().isEmpty() || node.getContentDescription().toString().isEmpty()))

但这可能不是您问题的结束,因为这也会捕获带有替代文本的图像,因此您可能需要使匹配更加复杂。

© www.soinside.com 2019 - 2024. All rights reserved.