Android AccessibilityService设置服务信息方法&x27;s变化不';在服务连接的外部,似乎不起作用

Android AccessibilityService设置服务信息方法&x27;s变化不';在服务连接的外部,似乎不起作用,android,accessibility,accessibilityservice,Android,Accessibility,Accessibilityservice,为setServiceInfo引用文档 “您可以随时调用此方法,但在系统绑定到此服务后以及此后调用此方法时,将获取信息。” 我的应用程序已启用可访问性,我已在onServiceConnected方法中设置serviceInfo,我正在接收这些应用程序的事件,一切正常 现在,问题是我试图通过在onServiceConnected方法之外调用setServiceInfo来修改包列表,但是更改没有生效(即我仍然从前面指定的包列表中的包接收事件,这些事件在修改的包列表中不存在) 可访问性\u服务\u c

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

我的应用程序已启用可访问性,我已在onServiceConnected方法中设置serviceInfo,我正在接收这些应用程序的事件,一切正常

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

可访问性\u服务\u config.xml

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


因此,问题是如何根据我以后收到的可访问性事件在可访问性服务中添加/删除包

不能通过将包名称添加到该列表中来排除它们

serviceInfo.packageNames = null
获取所有包的事件

serviceInfo.packageNames = {"some.package"}
仅获取某些.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.
}
您将覆盖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函数,并在
服务配置.xml
文件中静态地执行所有操作。

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

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

1. 第2786-2788行

if (packageNames != null) {
      mPackageNames.addAll(Arrays.asList(packageNames));
} 
2.
1428 Set packageNames=service.mPackageNames;
1429字符串packageName=(event.getPackageName()!=null)
1430                ? event.getPackageName().toString():null;
1431
1432返回(packageNames.isEmpty()| | packageNames.contains(packageName));

也许我说“排除”时不太清楚。让我解释一下。最初我想接收两个包“packageA”和“packageB”的事件,我在onServiceConnected中使用setServiceInfo设置了这两个包。稍后,在收到某个事件后,我想“排除”packageB,只想从packageA中删除事件。现在我修改了packageNames数组以只包含packageA并再次调用setServiceInfo,但我仍然从packageB接收事件。我目前使用的是u建议的方式,但我想为什么还要麻烦从packageB接收事件并返回,如果我可以取消订阅packageB。我注释掉的代码部分工作得非常好。i、 我收到了两个包的事件,就像我应该收到的一样。因此,我认为没有必要将有效的部分包括在内。如果有帮助,我很乐意与大家分享。说到“如果”一词,与其说是关于代码行,不如说是关于我不断接收的不必要事件的数量,当有人使用我不再感兴趣的软件包时,这些事件只会耗尽电池。注意:TalkBack不断地从所有软件包接收大多数事件类型的事件,在影响我电池寿命的应用程序列表中几乎没有出现。仅通过限制您的两个包,您就在这个场景中优化了很多。在我看来,这似乎是一个不必要的微观优化。尽管如此,我仍然对学术感兴趣!!!包括在内。为了方便起见,我将其限制为两个包。我列出了大约100个包。我将尝试提供更多的上下文。我正试图通过听你建议的启动程序活动[这里]()来检测Home按钮的按下。但是,一旦我知道用户按下home键,我就不再使用launcher活动中的事件,所以我想“排除”它。由于所讨论的程序包是启动程序活动,我担心我会在收听菜单中滚动之类的事件时耗尽电池。来回发送事件并不需要大量电池。TalkBack出现在“耗电”应用程序列表中,因为它始终在所有应用程序之上运行,因为它是一种无障碍服务。所以,是的,我肯定认为你说的是一个超微观优化,不值得。
//Get the object that has been initialized with settings from your service_config.xml file
AccessibilityServiceInfo accessibilityServiceInfo = getServiceInfo();
if (packageNames != null) {
      mPackageNames.addAll(Arrays.asList(packageNames));
} 
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));