原文链接:https://blog.csdn.net/to35998642/article/details/86236018
(1)辅助功能工具方法如下:
/**
* 辅助功能相关检查的帮助类
*/
public class AccessibilityUtil {
private static final String ACCESSIBILITY_SERVICE_PATH = AccessibilitySampleService.class.getCanonicalName();
/**
* 判断是否有辅助功能权限
*/
public static boolean isAccessibilitySettingsOn(Context context) {
if (context == null) {
return false;
}
int accessibilityEnabled = 0;
try {
accessibilityEnabled = Settings.Secure.getInt(context.getApplicationContext().getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
String packageName = context.getPackageName();
final String serviceStr = packageName + "/" + ACCESSIBILITY_SERVICE_PATH;
// AccessibilityLog.printLog("serviceStr: " + serviceStr);
if (accessibilityEnabled == 1) {
TextUtils.SimpleStringSplitter mStringColonSplitter = new TextUtils.SimpleStringSplitter(':');
String settingValue = Settings.Secure.getString(context.getApplicationContext().getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (settingValue != null) {
TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
splitter.setString(settingValue);
while (splitter.hasNext()) {
String accessabilityService = splitter.next();
if (accessabilityService.equalsIgnoreCase(serviceStr)) {
return true;
}
}
}
}
return false;
}
/**
* 打开辅助功能界面,需找到对应app点击打开即可
*/
public static Intent getAccessibilitySettingPageIntent(Context context) {
// 一些品牌的手机可能不是这个Intent,需要适配
return new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
}
}
(2)AccessibilityService服务不需要把注册写在代码里,将注册写在AndroidManifest.xml中,系统在读到程序需要此服务的时候就会自动注册到服务中,如下:
(3)由于AccessibilityService服务权限较大,所以需要手动启动,启动后,之后程序没有异常关闭(比如崩溃),服务就会一直处在开启状态,就算是关机重启,服务也是开着的。
(4)AccessibilityService服务需要写一个xml配置文件,如图:
其中packageNames为需要监控的包名,只有写在这里的app才会被监控,其他的app不受监控,也就是说如果想用AccessibilityService服务来自动点击自己app的view,那么首先要把自己app的包名写在这里
(5)AccessibilityService服务可以获取到手机当前屏幕上的所有view,包括布局,但只是当前页面的,如果页面可能上下滑动,那么没有显示在页面上的部分AccessibilityService服务也同样获取不到,需要滑动后,让需要的内容显示在当前屏幕上,AccessibilityService服务才可以获取到。
(6)AccessibilityService服务可以通过AccessibilityNodeInfo rootInActiveWindow = getRootInActiveWindow();获取当前页面的布局,然后通过view = rootInActiveWindow.findAccessibilityNodeInfosByViewId(viewid);或者view = rootInActiveWindow.findAccessibilityNodeInfosByText(textname);来获取到需要的view,前者是通过view的id查找view,后者是通过view的text属性查找view,找到view后,就可以对view进行点击操作了,
需要注意:
1.获取到的view是个集合,有可能同意id有多个view,所以需要遍历view集合,找到需要的view在进行操作。
2.AccessibilityService服务可以对view进行点击操作,但是不能修改view的属性,如果view的Clickable属性是false,代表view不可点击,也不能通过AccessibilityService服务将Clickable属性改为true
(7)当view为不可点击时,可以通过clickview = clickview.getParent();找到view的父view,然后对父view进行判断并点击,如果父view还是不可点击,可以继续往上找,要是都不能点击,那就认栽吧,哈哈......
(8)有时候,需要的view不在当前屏幕上,需要滑动一下才行,这时候可以使用android7.0提供的方法进行滑动,如下图:
图中红框部分代表滑动的起始点和结束点,500为x轴的位置,start和stop为y轴的位置,由于是从下往上滑动屏幕,所以起始点的y比结束点的y要大,可以理解为把手放在500,1050的位置,然后滑动到500,413的位置,也就是垂直向上滑动了页面
(9)有时候会遇到AccessibilityNodeInfo rootInActiveWindow = getRootInActiveWindow()为空的现象,而且是等多久获取都是空,这时候可以尝试下拉一下通知栏,这样做也等于是刷新AccessibilityService服务可以重新获取一下布局,方法如下:
其中expandStatusBar(Context ctx)方法是下拉方法,collapseStatusBar(Context ctx)是收回方法
(10)想要对view进行点击,可以用clickview.performAction(AccessibilityNodeInfo.ACTION_CLICK);
(11)想要点击物理回退键是,可以用performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
(12)直接模拟点击坐标,测试代码如下
(13)在打开手机指针位置的情况下,辅助点击和MotionEvent.obtain点击效果不同:
辅助模式模拟点击和滑动会出现痕迹,MotionEvent.obtain无痕迹留下