android - 在Android中使用辅助服务获取 Activity 的布局名称

标签 android android-layout accessibilityservice accessibility

我正在尝试创建一个应用程序来获取其他应用程序的包名称、 Activity 名称和 Activity 布局名称(XML)。为此,我使用辅助功能服务来获取前台窗口的 WINDOW_STATE_CHANGED。

我取得了什么成就?

我可以使用辅助功能服务获取其他应用程序的包名称和 Activity 名称。

我无法实现的目标!

我已经尝试了几乎所有可能的解决方案来获取 Activity 的布局名称,但不幸的是我每次连续的尝试都失败了。

到目前为止我已经尝试过:

第 1 步:

res/xml文件夹下创建accessibilityservice.xml,如下所示

<accessibility-service
    xmlns:tools="http://schemas.android.com/tools"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagIncludeNotImportantViews"
    android:canRetrieveWindowContent="true"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:ignore="UnusedAttribute"/>

第 2 步:

创建了WindowChangeDetectingService.java服务类并记录了包名称和 Activity ,如下所示

    import android.accessibilityservice.AccessibilityService;
    import android.accessibilityservice.AccessibilityServiceInfo;
    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.pm.ActivityInfo;
    import android.content.pm.PackageManager;
    import android.os.Build;
    import android.util.Log;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.accessibility.AccessibilityEvent;
    import android.view.accessibility.AccessibilityNodeInfo;

    import java.util.List;

    public class WindowChangeDetectingService extends AccessibilityService {

        @Override
        protected void onServiceConnected() {
            super.onServiceConnected();

            //Configure these here for compatibility with API 13 and below.
            AccessibilityServiceInfo config = new AccessibilityServiceInfo();
            config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
            config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;

            if (Build.VERSION.SDK_INT >= 16)
                //Just in case this helps
                config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;

            setServiceInfo(config);
        }

        @Override
        public void onAccessibilityEvent(AccessibilityEvent event) {

            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
                if (event.getPackageName() != null && event.getClassName() != null) {
                    ComponentName componentName = new ComponentName(
                        event.getPackageName().toString(),
                        event.getClassName().toString()

                    );


                    Log.i("AccessPackagename",  event.getPackageName().toString());
                    Log.i("AccessgetClassName",  event.getClassName().toString());

                }
            }
        }
}

第3步:在manifest.xml中创建注册WindowChangeDetectingService,如下所示

<service
            android:name=".WindowChangeDetectingService"
            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/accessibilityservice"/>
        </service>

输出:(从 Logcat 检索)

08-18 12:51:45.430 11206-11206/com.takeoffandroid.screenlog I/AccessPackagename: com.takeoffandroid.screenlog
08-18 12:51:45.430 11206-11206/com.takeoffandroid.screenlog I/AccessgetClassName: com.takeoffandroid.screenlog.MainActivity

我的要求:(预期输出)

08-18 12:51:45.430 11206-11206/com.takeoffandroid.screenlog I/AccessPackagename: com.takeoffandroid.screenlog
    08-18 12:51:45.430 11206-11206/com.takeoffandroid.screenlog I/AccessgetClassName: com.takeoffandroid.screenlog.MainActivity

--------------------------------------------------------------------    --------------------------------------------------------------------

    08-18 12:51:45.430 11206-11206/com.takeoffandroid.screenlog I/AccessgetLayoutName: activity_main.xml //Should be capable to read the layout name of the MainActivity

--------------------------------------------------------------------   --------------------------------------------------------------------

过去两天我一直在努力解决这个要求,但无法找到任何方法或方法在 Android 中使用辅助功能服务来做到这一点。任何帮助或建议都会对我非常有帮助。提前致谢。

最佳答案

您需要修改服务配置以将 View ID 名称包含在辅助功能节点信息中。

<accessibility-service
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagReportViewIds|flagIncludeNotImportantViews"
android:canRetrieveWindowContent="true"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="UnusedAttribute"/>

这里的重要变化是:

android:accessibilityFlags="flagReportViewIds|flagIncludeNotImportantViews"

或者更具体地说这部分:

flagReportViewIds

此外,您不应包含 onServiceConnected 函数。您正在修改 service_config xml 文件中所做的所有配置。你也没有完全正确地做到这一点。创建新的服务信息是危险的,因为您不太可能填充所有重要的字段。这一行:

AccessibilityServiceInfo config = new AccessibilityServiceInfo();

应该是这样的:

AccessibilityServiceInfo config = getServiceInfo()

然后修改它!不过,说真的,不要这样做,只需依赖 service_config XML 属性即可。

一旦您进行了正确的配置,您应该能够执行以下操作:

someAccessibilityNodeInfo.getViewIdResourceName()

这是您要查找的 ID。

关于android - 在Android中使用辅助服务获取 Activity 的布局名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45750884/

相关文章:

accessibilityservice - Android 无障碍服务在 Oreo 上一两天后停止工作

android - 使用无障碍服务

java - 如何在Android中获取HashMap在java上循环的内容?

android - 相对于 drawableLeft 图像垂直居中 TextView 的文本

android - 透明 RelativeLayout 容器内的不透明 TextView

android - 如何为线性布局元素设置 setLayoutParams

用于动态添加 View 的 Android 布局占位符

android - AccessibilityService 如何利用其他应用程序?

java - 主线程: can runnables be preempted?

android - Activity 重启问题