第一、寻找到我们想要的View节点
第二、而后模拟点击,实现特定功效
我们晓得Android中的View体系是一个树形结构,辣么每一个View即是一个节点。所以我们可以查找到指定的节点,辣么我们该若何查找到我们想要的节点呢?这里我们先看一下辅助功效(AccessibilityService)的用法。
第一步、我们必要集成AccessibilityService类
我们必要自定一个Service而后秉承AccessibilityService,固然还必要在AndroidManifest.xml中申明这个服无:
<application> <service android:name=".MyAccessibilityService" android:label="@string/accessibility_service_label"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <mate-data android:name="android.accessibilityservice" anroid:resource="@xml/accessibility"/> </service> <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" /> </application>
在<application>标签下增加指定了AccessibilityService的子类MyAccessibilityService,同时加入响应的权限。
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
固然还要一个meta-data的申明,这个申明是对这个AccessibilityService的配置。我们看一下配置文件内容:
(注:从Android4.0开始,开发者可以通过在AndroidManifest里增加<meta-data>标签,在标签里指出配置文件的位置)
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagDefault" android:canRetrieveWindowContent="true" android:description="@string/desc" android:notificationTimeout="100" android:packageNames="com.tencent.妹妹" />
这里我们看到有良多选项,我们看一下常用的几个属性:
1、android:accessibilityEventTypes="typeAllMask"
看属性名也差不多可以清晰,这个是用来配置响应事件的范例,typeAllMask固然即是响应所有范例的事件了。固然另有单击、长按、滑动等。
2、android:accessibilityFeedbackType="feedbackSpoken"
配置回馈给用户的体例,有语音播出和振动。可以配置少许TTS引擎,让它实现发音。
3、android:notificationTimeout="100"
响应时间的配置就不用多说了
4、android:packageNames="com.example.android.apis"
可以指定响应某个运用的事件,这里由于要响应所有运用的事件,所以不填,默认即是响应所有运用的事件。好比我们写一个微信抢红包的辅助程序,便在这里填写微信的包名,便可以监听微信产生的事件了。我们这些配置信息除了在xml中定义,一样也能够在代码中定义,我们普通都是在onServiceConnected()要领里进行
@Override protected void onServiceConnected() { AccessibilityServiceInfo info = getServiceInfo(); info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN; info.notificationTimeout = 100; setServiceInfo(info); info.packageNames = new String[]{"xxx.xxx.xxx", "yyy.yyy.yyy","...."}; setServiceInfo(info); super.onServiceConnected(); }
在子类MyAccessibilityService里实现几个紧张的重载要领:
onServiceConnected() - 可选。体系会在胜利持续上你的服无的时候挪用这个要领,在这个要领里你可以做一下初始化事情,比方建筑的声响触动经管,也能够挪用setServiceInfo()进行配置事情。
onAccessibilityEvent() - 必需。通过这个函数可以汲取体系发送来的AccessibilityEvent,汲取来的AccessibilityEvent是经过过滤的,过滤是在配置事情时配置的。
onInterrupt() - 必需。这个在体系想要中缀AccessibilityService返给的响应时会挪用。在全部性命周期里会被挪用屡次。
onUnbind() - 可选。在体系将要关闭这个AccessibilityService会被挪用。在这个要领中进行少许释放资源的事情。
2、这里我们普通都会在这里写上我们必要监听的运用的包名,不过偶然候我们必要监听多个运用,辣么这时候我们该怎么办呢?
第一种:我们在代码中注册多个运用的包名,从而可以监听多个运用:
@Override protected void onServiceConnected() { AccessibilityServiceInfo info = getServiceInfo(); //这里可以配置多个包名,监听多个运用 info.packageNames = new String[]{"xxx.xxx.xxx", "yyy.yyy.yyy","...."}; setServiceInfo(info); super.onServiceConnected(); }
第二种:我们在onAccessibilityEvent事件监听的要领中做包名的过滤(这种体例最常用)
@Override public void onAccessibilityEvent(AccessibilityEvent event) { String pkgName = event.getPackageName().toString(); if("xxx.xxx.xxx".equals(pkgName)){ }else if("yyy.yyy.yyy".equals(pkgName)){ }else if("....".equals(pkgName)){ } }
第三步、在onAccessibilityEvent要领中监听指定的事件
这内部最紧张的片面即是onAccessibilityEvent这个回调函数,当我们注册了监听事件的时候,当有事件产生就会关照我们这个函数,不过必然要留意这个函数关照是异步的,固然良多伴侣就会问这个是怎么关照到这里来的呢?他是通过AccessibilityDelegate这个代劳类,发送出来的,这个类有个要领sendAccessibilityEvent可以发送事件。那这个类又怎么和我们的窗口接洽呢?这里举个例子。好比我们的View类内部有个setAccessibilityDelegate这个要领,是不是这下统统都清晰了呢?而后即是挪用我们的find函数去目前节点内部找到我们必要的节点信息。
@Override public void onAccessibilityEvent(AccessibilityEvent event) { int eventType = event.getEventType(); switch (eventType) { case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: //....... } }
这个事件范例良多的,我们可以查看AccessibilityEvent类的源码
第四步、查找到我们想要处分的节点View
这里体系提供了两个要领让我们来进行查找想要的节点View
第一种是通过节点View的Text内容来查找
findAccessibilityNodeInfosByText("查找内容")
这种体例查找,即是像TextView,Button等View有文本内容的,可以应用这种体例疾速的找到。
第二种是通过节点View在xml结构中的id称号
findAccessibilityNodeInfosByViewId("@id/xxx")
这个普通很难晓得,不过我们在查找体系控件的时候照旧可以做的,由于体系的控件的id是可以晓得的,并且是同一的。
(对于这两个要领我们在写网络爬虫程序的时候可能晓得,在html中通过tag/name/id等信息可以找到一个节点,道理都相似)
第五步、模拟点击指定事件
我们找到我们想要的View节点,挪用要领模拟事件:
performAction(AccessibilityNodeInfo.ACTION_CLICK)
挪用这个要领即可,固然这里的参数即是指定事件的称号,这个和AccessibilityEvent中监听的那些事件是逐一对应的,这里是模拟点击事件,我们固然可以模拟View的转动事件,长按事件等。