一、前言node
网上关于Android辅助服务的使用方式已经很是丰富了,因此也不在意再多我这一篇了:-D。有同窗说这是重复造轮子,题主很赞成,但反过来讲,若是本身没有能力造出轮子,还对重复造轮子嗤之以鼻,那……,再者,题主认为,本身重复一遍别人的轮子,踩踩坑,要比只看别人的轮子在理解上深入的多,再不济,记录下来权当笔记吧android
二、实现步骤web
一、自定义服务继承系统的AccessibilityService服务,重写必要方法api
二、配置AndroidManiFest.xml,增长服务相关配置ide
三、在res下新建文件夹xml,新建xml文件,配置服务的相关配置,并在AndroidManifest.xml指定该配置文件(也能够在服务类的onServiceConnected中配置)测试
四、打包、安装apk,在“设置里”找到辅助服务并开启便可。ui
三、具体实现spa
一、自定义服务,必须实现的方法是onAccessibilityEvent(AccessibilityEvent event)和onInterrupt(),代码以下.net
public class AccessibilityServiceTest extends AccessibilityService { //可在此方法中配置服务的相关配置,代替配置文件的方式 @Override protected void onServiceConnected() { super.onServiceConnected(); Log.d("XLZH:", "OnServiceConnected"); } //监听事件类型,根据事件类型不一样作不一样的处理。事件类型较多,各位能够打印出来筛选出来本身要监听的事件类型 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN) @Override public void onAccessibilityEvent(AccessibilityEvent event) { Log.d("XLZH:", event.toString()); int eventType = event.getEventType(); switch (eventType) { case AccessibilityEvent.TYPE_VIEW_SCROLLED: //获取发生该事件的页面根view AccessibilityNodeInfo nodeInfo = getRootInActiveWindow(); //根据id查找须要点击的节点,返回的是一个List List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("com.tendcloud.demo:id/pager"); //获取List的第一个节点,并打印该节点的child数目及类名 AccessibilityNodeInfo contentNodeInfo = list.get(0); Log.d("XLZH size:", String.valueOf(contentNodeInfo.getChildCount())); Log.d("XLZH class: ", String.valueOf(contentNodeInfo.getClassName())); //经过查找文本的方式得到节点
if(contentNodeInfo.findAccessibilityNodeInfosByText("button_test1") != null){ Log.d("XLZH :", "first page"); } if(contentNodeInfo.findAccessibilityNodeInfosByText("button1") != null){ Log.d("XLZH :", "second page"); } if(contentNodeInfo.findAccessibilityNodeInfosByText("tvweb") != null){ Log.d("XLZH :", "third page"); } break; } } @Override public void onInterrupt() { } }
二、配置AndroidManiFest.xml。以下code
<service android:name=".AccessibilityServiceTest" android:label="AccessibilityServiceTest" <!--声明权限,而不是申请权限-->
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" android:exported="false"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <!--配置服务服务配置文件路径--> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_xml" /> </service>
三、编写辅助服务的配置文件
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/description" //在设置中显示的内容 android:accessibilityEventTypes="typeAllMask" //监听事件的类型 android:accessibilityFeedbackType="feedbackGeneric" //反馈的类型 android:notificationTimeout="100" //设置超时时间 android:accessibilityFlags="flagDefault" //配置flag android:canRetrieveWindowContent="true" //能够获取窗口上的对象的值 android:packageNames="com.tendcloud.demo" /> //配置要监听的包名
四、其余
一、有个印象深入的坑是在配置AndroidManifest.xml时,不是使用<user-permission ...>,而是要在Service里声明服务,即有BIND_ACCESSIBILITY_SERVICE的应用才能访问该服务,而不是该服务须要申请这个权限
二、原本想是否能够只要该Service,而不要Activity,通过查阅资料、亲自尝试,结果是……不行!
三、还有一个坑,至今没有解决。测试的目的apk界面, 以下
如代码所示,原本想经过查找控件肯定当前是那个页面,测试结果发现当在第一个页面的时候,Child包括第二个页面中的控件,当在第二个页面的时候,Child包括第一个、第2、第三个页面中的控件,当在第三个页面的时候,Child包括第二个页面和第三个页面中的控件。
具体缘由不明白,有大神能够测试并指导一下,谢谢。