将可访问性事件传递给后台线程获取 null

Posted

技术标签:

【中文标题】将可访问性事件传递给后台线程获取 null【英文标题】:Passing Accessibility Event to backthread getting null 【发布时间】:2018-11-01 01:10:48 【问题描述】:

尝试使用 android AccessibilityService,将 AccessibilityEvent 传递给 AsyncTask,但 AccessibilityEvent 中的所有值都消失了,例如 mEventTime 变为 0,mPackageName 变为 null 等。无法理解这里发生了什么

public class MyAccessibilityService extends AccessibilityService 

public void onAccessibilityEvent(AccessibilityEvent event) 
    new MyTestAsync().execute(event); //event not null 


 public class MyTestAsync extends AsyncTask<Object, Void, Void> 

        private AccessibilityEvent event;

        @Override
        protected ArrayList<AccessibilityNodeInfo> doInBackground(Object... params) 
               this.event = (AccessibilityEvent) params[0]; //getting null values in event  like mEventTime = 0, mPackageName = null


捕获以下类型的事件

android:accessibilityEventTypes="typeWindowStateChanged|typeViewFocused|typeWindowContentChanged"

【问题讨论】:

您可以将可访问性提取的数据传递给您的异步任务,但在 onAccessibilityEvent() 中创建异步任务非常糟糕,因为此方法将在每个事件上调用,并且系统中的异步任务数量有限制 @MirzaAhmedBaig 你提醒我注意一些 AsyncTask 限制,但我的主要动机是在获取 AccessibilityEvent 后在后台进行所有处理。是的,我可以将可访问性提取的数据传递给我的异步任务,但尝试理解为什么会为空。 嘿,伙计,你有什么东西吗?? 直到现在... 您有解决方案吗?即使我也面临着类似的问题。 【参考方案1】:

事件对象可以被操作系统重用。接收者不拥有它。操作系统不会不断地创建新事件。事实上,在正常情况下它只创建很少的可重用(甚至可能只有 1 个)。通过在后台线程中处理事件,事件对象中的值在您开始处理它们时完全无效。你很幸运,它们都是空的,而不是随机的,会让你相信这种方法是伪有效的。

解决方案:创建您自己的事件包装器,从您需要的事件中复制值,然后将其传递给您的 AsyncTask。

【讨论】:

感谢您的回复,如果可能请提供样本。 Chris 如何创建事件包装器? 如果您必须爬取与事件关联的 AccessibilityNode 树,则该解决方案没有用处。使用 AccessibilityEvent.obtain(originalEvent) 创建一个副本,然后将其传递给后台线程。【参考方案2】:

您在AccessibilityService#onAccessibilityEvent 中交给您的事件对象仅在该方法调用期间有效。

如果您需要推迟使用它,您可以使用AccessibilityEvent.obtain(originalEvent) 进行复制,然后传递该新对象。

【讨论】:

以上是关于将可访问性事件传递给后台线程获取 null的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:如何将可访问性焦点集中到自定义应用栏

Xamarin iOS - 我们如何以编程方式将可访问性焦点设置为按钮

必须将 NetInfo 传递给 networkMonitor 以启用 React Native 中的可访问性

了解线程中的变量可访问性

框架方法可访问性中的桥接头

在可访问性中为 ionic 中的切换按钮启用点击或单击事件