2

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

我取得了什么成就?

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

我无法实现的!

我已经尝试了几乎所有可能的解决方案来获取 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服务类并记录包名称和活动,如下所示

    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 步:注册 WindowChangeDetectingService 在 manifest.xml 中创建,如下所示

<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 中使用 Accessibility Service 找到任何方法或方法来实现此要求。任何帮助或建议都会对我很有帮助。提前致谢。

4

1 回答 1

3

您需要修改服务配置以在可访问性节点信息中包含视图 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。

于 2017-08-20T21:25:29.523 回答