商务网站建设学期总结,做网站哪家,河南大宗商品交易平台,响应式企业网站源码Android 辅助服务#xff08;AccessibilityService#xff09;旨在帮助具有视觉、身体或年龄相关限制的用户更轻松地使用 Android 设备和应用。通过辅助服务#xff0c;可以将一些人工操作自动化#xff0c;从而解放用户的双手。 因此我们可以使用它来实现一些自动化任务AccessibilityService旨在帮助具有视觉、身体或年龄相关限制的用户更轻松地使用 Android 设备和应用。通过辅助服务可以将一些人工操作自动化从而解放用户的双手。 因此我们可以使用它来实现一些自动化任务比如抢红包测试自动玩游戏(外挂)。author: https://blog.csdn.net/keeng2008
编写辅助服务MyAccessibilityService,继承AccessibilityService
class MyAccessibilityService : AccessibilityService() {override fun onServiceConnected() {super.onServiceConnected()Log.i(TAG, onServiceConnected)}override fun onAccessibilityEvent(event: AccessibilityEvent) {Log.i(TAG, onAccessibilityEvent: $event)val packageName event.packageName/* 处理界面变动事件 */}override fun onInterrupt() {Log.i(TAG, onInterrupt)}
}当辅助服务开启后Service会开始运行界面上的元素变动窗口变动会回调onAccessibilityEvent。在其中可以实现模拟点击。
这个服务不能主动开启需要用户在设置-无障碍中手动开启。
把MyAccessibilityService添加到Manifest serviceandroid:name.accessbi.MyAccessibilityServiceandroid:exportedtrueandroid:label控制辅助服务Demoandroid:permissionandroid.permission.BIND_ACCESSIBILITY_SERVICEintent-filteraction android:nameandroid.accessibilityservice.AccessibilityService //intent-filtermeta-dataandroid:nameandroid.accessibilityserviceandroid:resourcexml/my_accessibility //service在res/xml中添加文件 my_accessibility.xml
?xml version1.0 encodingutf-8?
accessibility-service xmlns:androidhttp://schemas.android.com/apk/res/androidandroid:accessibilityEventTypestypeAllMaskandroid:accessibilityFeedbackTypefeedbackSpokenandroid:accessibilityFlagsflagReportViewIdsandroid:canRetrieveWindowContenttrueandroid:canPerformGesturestrueandroid:notificationTimeout100/这样就已经注册好辅助服务但是需要用户手动到“设置”中的“无障碍”去启动无障碍功能。
引导用户直接跳转到无障碍中启动
3.1 判断当前是否已经启动 fun isAccessibilitySettingsOn(context: Context): Boolean {val accessibilityEnabled Settings.Secure.getInt(context.contentResolver,Settings.Secure.ACCESSIBILITY_ENABLED)if (accessibilityEnabled ! 1) return falseval value Settings.Secure.getString(context.contentResolver,Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES) ?: return falsereturn value.contains(context.packageName) value.contains(MyAccessibilityService::class.java.simpleName)}3.2 跳转到无障碍设置界面 发现未开启服务后引导用户跳转到设置界面手动打开。 fun openAccessibilitySetting(context: Context) {val intent Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)context.startActivity(intent)}3.3 开启后能否保持状态 经测试如果进程被主动杀死重启那么开关就被关闭了。 其它情况下即使关机重启更新APP它的状态能保持-
AccessibilityService常用方法
获取当前的APP: val packageName event.packageName获取当前的Activity: fun getActivityName(context: Context, event: AccessibilityEvent): String {val componentName ComponentName(event.packageName.toString(), event.className.toString())try {var activityName context.packageManager.getActivityInfo(componentName, 0).toString()activityName activityName.substring(activityName.indexOf( ), activityName.indexOf(}))return activityName} catch (e: Exception) {}return }不是每个event都能获取到Activity的比如一些ToastDialog的事件拿不到Activity; 所以可以把最后的Activity保存起来随时读取。
通过文本获取当前界面的View
fun findViewByText(svr: AccessibilityAble, text: String): AccessibilityNodeInfo? {val nodes svr.getRootNode()?.findAccessibilityNodeInfosByText(text)if (nodes ! null) {for (node in nodes) {if (node.text text) {return node}}}return nodes?.firstOrNull()
}AccessibilityAble: 主是要封装了对 getService().rootInActiveWindow 的引用, 这样可以从当前的全局根结点开始寻找。
通过viewId获取当前界面的View 格式示例 “APP包名:id/operator_normal_iv”
fun findViewById(svr: AccessibilityAble, viewId: String): AccessibilityNodeInfo? {val nodes svr.getRootNode()?.findAccessibilityNodeInfosByViewId(viewId)return nodes?.firstOrNull()
}模拟View点击
val btn: AccessibilityNodeInfo? AccessibilityUtils.findViewByText(svr, 下次再说)
if (btn ! null btn.isClickable btn.isVisibleToUser) {btn.performAction(AccessibilityNodeInfo.ACTION_CLICK)
}通过手势长按指定坐标
fun performLongPress(svr: AccessibilityAble, point: PointF, durationMill: Long) {// 创建手势描述val gestureBuilder GestureDescription.Builder()// 移动到指定坐标val path Path().apply {moveTo(point.x, point.y)}val duration: Long durationMill // 持续时间 毫秒val strokeDescription GestureDescription.StrokeDescription(path, 0, duration)// 添加手势到描述gestureBuilder.addStroke(strokeDescription)val gesture gestureBuilder.build()// 执行手势val cb object : AccessibilityService.GestureResultCallback() {override fun onCompleted(gestureDescription: GestureDescription?) {Log.i(TAG, onCompleted, $gestureDescription)}override fun onCancelled(gestureDescription: GestureDescription?) {Log.i(TAG, onCancelled, $gestureDescription)}}val res svr.getService().dispatchGesture(gesture, cb, null)Log.i(TAG, dispatchGesture, res: $res)
}点击Node所在位置:主要是有些文本不可点击直接模拟点击该位置
fun performClick(svr: AccessibilityAble, node: AccessibilityNodeInfo) {val rect Rect()node.getBoundsInScreen(rect)val centerP PointF(rect.exactCenterX(), rect.exactCenterY())Log.i(TAG, Start Simple Click at $centerP)performLongPress(svr,centerP,100L)
}author: https://blog.csdn.net/keeng2008 有了这神器能实现些什么新奇玩法呢抢红包自动打卡继续探索中。