【问题标题】:AccessibilityService setServiceInfo method's changes don't seem to take effect outside onServiceConnectedAccessibilityService setServiceInfo 方法的更改似乎在 onServiceConnected 之外没有生效
【发布时间】:2017-10-14 19:05:05
【问题描述】:

引用 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"
/>

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

【问题讨论】:

    标签: android accessibility accessibilityservice


    【解决方案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 文件中静态地执行所有操作。

    【讨论】:

    • 也许当我说“排除”时我不是很清楚。让我解释一下。最初我想接收我在 onServiceConnected 中使用 setServiceInfo 设置的两个包“packageA”和“packageB”的事件。稍后在我收到某个事件后,我想“排除”packageB,只想要来自 packageA 的事件。现在我修改 packageNames 数组以仅包含 packageA 并再次调用 setServiceInfo,但我仍然从 packageB 接收事件。我目前正在使用你建议的方式,但我想为什么还要费心从 packageB 接收事件并返回如果我可以取消订阅 PackageB .
    • 我注释掉的代码部分工作得很好。即我正在像我应该的那样从两个包中接收事件。所以,我认为包含有效的部分没有任何意义。如果有帮助,我很乐意分享它。来到一个“if”语句,与其说是代码的行数,不如说是代码的数量当有人使用我不再感兴趣的包裹时,我不断收到不必要的事件,只会耗尽电池电量。
    • 注意:TalkBack 会不断地从所有程序包中接收大多数事件类型的事件,并且几乎不会出现在影响我的电池寿命的应用程序列表中。仅通过限制您的两个软件包,您就已经在这种情况下优化了 TON。这对我来说,似乎是一个不必要的微优化。不过,我仍然对学术感兴趣!!!
    • 包括在内。为方便起见,我将其限制为两个包。我列出了大约 100 个包。我会尝试提供更多背景信息。我正在尝试通过聆听您在 [此处] (stackoverflow.com/a/43158274/5551621) 中建议的启动器活动来检测主页按钮的按下情况。但是,一旦我知道用户按下了主页,我就不再使用启动器活动中的事件,所以我想“排除”它。由于有问题的包是启动器活动,我担心我会在听诸如滚动菜单之类的事件时耗尽电池。
    • 来回发送事件不会消耗大量电池。 TalkBack 出现在“耗电”应用程序列表中,因为它始终运行在一切之上,因为它是一项无障碍服务。所以,是的,我绝对认为你在谈论的是超级微优化,不值得。
    【解决方案2】:

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

    原因在于以下两种方法。在#1 中,当您调用 setServiceInfo(info) 时 info.mPackageNames 为空,这里它只是跳过它并且从不将 service.mPackageNames 设置为空。在 #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));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      相关资源
      最近更新 更多