Android Accessibility安卓辅助功能开发总结
本文从 https://blog.csdn.net/qq_15784961/article/details/72742199 文章进行增改和自己遇到问题的一些总结,方便自己以后查找,侵删。
Android Accessibility是google开放的为无障碍辅助开发的api。
AccessibilityService是一个可以继承的Service类,注册后,系统会把配置监测的应用行为,通知给这个service。
一、新建类继承AccessibilityService并重写方法
- onAccessibilityEvent(AccessibilityEvent event)必须重写。AccessibilityEvent是一个事件类,里面封装了许多字段,表示各种不同的事件(通知、窗口内容)。形参event表示事件变化,接收来的AccessibilityEvent是可以经过过滤的,过滤是在配置工作时设置的。
- onInterrupt()必须重写。这个在系统想要中断AccessibilityService返给的响应时会调用。在整个生命周期里会被调用多次。
- onServiceConnected()可选。在系统成功连接上这个AccessibilityService会调用。在这个方法里主要做初始化工作。
- onUnbind()可选。在系统将要关闭这个AccessibilityService会被调用。在这个方法中主要做释放资源的工作。
二、AndroidManifest.xml声明该Service
<service
android:name=".AutoShareService"
android:enabled="true"
android:exported="true"
android:label="@string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
</service>
- 配置 <intent-filter> ,其name为固定值
- 声明 BIND_ACCESSIBILITY_SERVICE 权限
三、AccessibilityService添加配置信息(可选)
目的是只接收特定事件,例如:监听特定包名应用。android提供2种配置方法:
- meta-data标签方式
在manifest声明的Service中提供一个meta-data标签,然后通过android:resource指定相应的配置文件(在res目录下创建xml文件,并在其中创建配置文件auto_share_service_config.xml):
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/auto_share_service_config"
/>
- 调用setServiceInfo(AccessibilityServiceInfo)方式
AccessibilityServiceInfo用于配置AccessibilityService信息,类中包含了大量用于配置的常量字段。- 这个方法可以在任何时候调用,动态的去改变service配置信息
- 这个方法只能用来配置动态属性,如:eventTypes,feedbackType,flags,notificationTimeout等。通常是在onServiceConnected()进行配置
四、安装应用,提示用户去设置打开辅助功能
安装成功后,在设置->辅助功能中便可以找到我们的服务.该服务默认处在关闭状态,需要手动开启。
这个时候,在Service中回调方法中输出日志,发现已经可以接收到其它应用的触发事件。
PS:如果onServiceConnected触发onAccessibilityEvent不触发,那么可能是程序出现了ANR,崩溃后AccessibilityServices就失效了,重启手机即可
五、业务代码示例
接收响应:
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
int eventType = event.getEventType();
LogUtil.d(TAG, "接收到事件" + eventType);
CharSequence className = event.getClassName();
//这个<ClassName>可以调试,去获取你想要监测的页面的className
if (className.equals("<ClassName>")) {
//do what you want
}
}
获取界面元素:
AccessibilityService 中的方法 getRootInActiveWindow() 可以获取到当前激活的根Window对象,通过 findAccessibilityNodeInfosByViewId() 或者 findAccessibilityNodeInfosByText() 查找界面元素来修改或者操作。
详细的api可以百度。
模拟点击button:
/**
* 找到,text为发表的button,模拟点击
*/
private void clickShare() {
AccessibilityNodeInfo rootInActiveWindow = getRootInActiveWindow();
List<AccessibilityNodeInfo> list = rootInActiveWindow.findAccessibilityNodeInfosByText("发表");
if (list != null && list.size() != 0) {
for (AccessibilityNodeInfo accessibilityNodeInfo : list) {
if (accessibilityNodeInfo.getClassName().equals("android.widget.Button") && accessibilityNodeInfo.isEnabled()) {
accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
}
自动为EditView添加文本:
/**
* 找到id为ViewId的EditView,添加文本。可以通过Android Sdk文件中的monitor.bat工具,的Dump View Hierarchy for UI Automator按钮,找到当前页面上任意元素的id,具体可参考下面截图
*/
private void addEditText(String text) {
AccessibilityNodeInfo rootInActiveWindow = getRootInActiveWindow();
List<AccessibilityNodeInfo> list = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
list = rootInActiveWindow.findAccessibilityNodeInfosByViewId("<ViewId>");
}
if (list != null && list.size() != 0) {
for (AccessibilityNodeInfo accessibilityNodeInfo : list) {
if (accessibilityNodeInfo.getClassName().equals("android.widget.EditText") && accessibilityNodeInfo.isEnabled()) {
Bundle arguments = new Bundle();
arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
}
}
}
}
利用monitor.bat查找View id的图示:

参考: https://blog.csdn.net/qq_15784961/article/details/72742199

浙公网安备 33010602011771号