AccessibilityService setServiceInfo方法的更改似乎不会在onServiceConnected之外生效

时间:2017-10-14 19:05:05

标签: android accessibility accessibilityservice

引用setServiceInfo的文档 "您可以随时调用此方法,但系统绑定到此服务后以及此后调用此方法时将获取信息。"

我的应用程序已启用辅助功能,我已在onServiceConnected方法中设置了serviceInfo,并且我正在接收这些应用程序的事件,一切都很顺利。

现在,问题是我试图通过在onServiceConnected方法之外调用setServiceInfo来修改包列表,但是更改没有生效(即我仍然从包中的包接收事件前面指定的列表,在修改的包列表中不存在。)

@Override
protected void onServiceConnected() {
    AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo();
    accessibilityServiceInfo.packageNames = new String[]{"packageA","packageB"};
    accessibilityServiceInfo.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
            | AccessibilityEvent.TYPE_VIEW_SCROLLED | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
            | AccessibilityEvent.TYPE_VIEW_FOCUSED | AccessibilityEvent.TYPE_VIEW_SELECTED
            | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
    accessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
    accessibilityServiceInfo.notificationTimeout = 100;
    accessibilityServiceInfo.flags = (AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS | accessibilityServiceInfo.flags);
    setServiceInfo(accessibilityServiceInfo);
}

@Override
public void onAccessibilityEvent(final AccessibilityEvent event) {
    AccessibilityServiceInfo serviceInfo = getServiceInfo();
    serviceInfo.packageNames = new String[]{"packageA"};
    setServiceInfo(serviceInfo);
}

accessibility_service_config.xml

<accessibility-service 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_service_description"
/>

所以,问题是如何根据我稍后收到的辅助功能事件在辅助功能服务中添加/删除包?

2 个答案:

答案 0 :(得分:1)

您不能通过将包名称添加到该列表来排除包名称。

serviceInfo.packageNames = null

获取所有套餐的活动。

serviceInfo.packageNames = {"some.package"}

仅为some.package获取活动。此列表不是排除项,它是仅包含的事项列表。

现在,如果您可以保留要为其获取事件的所有包的列表,则可以执行此操作。动态设置服务信息只是花花公子!但是,TBH,你这样做太难了,而且没有按照预期的方式使用这个API。如果你只想排除一些东西,建议在世界上保存每个其他包名的列表,以获取他们的活动。在我看来,你需要自己的逻辑过滤器包名称。我会尝试这样做:

@Override
public void onAccessibilityEvent(AccessibilityEvent e) {

    //Do the filtering yourself.
    ArrayList<String> includedPackageNames = youlist;

    if (!includedPackageNames.contains(e.getPackageName())) return;

    //Do the rest of your stuff here.
}

编辑:

您的服务信息存在问题。当你这样做时:

@Override
protected void onServiceConnected() {
    AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo(); //This one!
    ...
}

您将覆盖service_config.xml文件中的所有信息以及您未在其中设置的任何默认值。您应该让service_config.xml处理静态初始化,并且只通过修改获取的serviceInfo对象来进行动态更改。或者,至少,从服务配置中获取已构建的那个。

将该行更改为:

//Get the object that has been initialized with settings from your service_config.xml file
AccessibilityServiceInfo accessibilityServiceInfo = getServiceInfo();

或者,更好的是,删除整个onServiceConnected函数,并在service_config.xml文件中静态执行。

答案 1 :(得分:1)

最近遇到了相同的问题。在研究了源代码(SDK 8.1)之后,似乎API描述给出了错误的期望,即将packageNames设置为某些应用程序列表,然后将其设置为null会使服务再次接收所有事件。

原因在下面的两种方法中。在#1中,当它调用setServiceInfo(info)(其中info.mPackageNames为null)时,它只是跳过了它,并且从未将service.mPackageNames设置为null。在#2中,当mPackageNames已包含您之前添加的应用程序时。因此,以后的mPackageNames.isEmpty()始终为false。

http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java#mPackageNames

1

第2786-2788行

if (packageNames != null) {
      mPackageNames.addAll(Arrays.asList(packageNames));
} 

2

1428 Set<String> packageNames = service.mPackageNames;
1429        String packageName = (event.getPackageName() != null)
1430                ? event.getPackageName().toString() : null;
1431
1432        return (packageNames.isEmpty() || packageNames.contains(packageName));