版权声明:本文为博主原创文章,未经博主允许不得转载。技术交流可邮:[email protected] https://blog.csdn.net/cjh94520/article/details/50328927
目录
用 [TOC]
来生成目录:
- 目录
- 简介
- 配置
- 实操
- 抢红包思路
-
-
- 监听微信应用发出的Notification检查字段是否有微信红包字段
- 点击Notification进入微信界面
- 调用getRootInActiveWindow获取根节点
- 调用findAccessibilityNodeInfosByText领取红包获取该节点
- 调用performActionAccessibilityNodeInfoACTION_CLICK实现模拟点击
- 坑点
- 包被混淆之前通过Android Device Monitor查看ID然后根据findAccessibilityNodeInfosByID去匹配节点包被混淆之后每个版本不一样
- 很难找出没有文本的控件如EditTextImageView
- 锁屏抢红包要解除锁屏isKeyguardLocked方法错误理解刚开始写代码的时候默认检测是否有锁屏如果锁屏了调用disableKeyguard解锁然后再检测是否真正解锁成功解锁之后再进行抢红包的逻辑后面发现disableKeyguard并不是真正能够解锁只是隐藏了锁屏
-
-
简介
AccessibilityService是一个辅助类,可以监听我们手机的焦点,窗口变化,按钮点击等等。实现它的服务需要在手机设置里面->辅助功能在这里面找到你自己实现的辅助类,然后打开它就可以进行我们一系列的监听了。还可以对监听的对象进行一些脚本的操作。
配置
Manifest.xml配置
新建一个类继承AccessibilityService,并在AndroidManifest文件里注册它,加入对应的Intent-filter,表明是一个辅助服务,同时加入相应的权限.
<application>
<service android:name=".MyAccessibilityService"
android:label="@string/accessibility_service_label">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
</service>
<uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
</application>
配置辅助服务
在代码中配置
一般在onServiceConnected()方法里进行
private void setServiceInfo(int feedbackType) {
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
// We are interested in all types of accessibility events.
info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
// We want to provide specific type of feedback.
info.feedbackType = feedbackType;
// We want to receive events in a certain interval.
info.notificationTimeout = EVENT_NOTIFICATION_TIMEOUT_MILLIS;
// We want to receive accessibility events only from certain packages.
info.packageNames = PACKAGE_NAMES;
setServiceInfo(info);
}
在xml文件中配置
从Android4.0开始,开发者可以通过在AndroidManifest里添加标签
<service android:name=".MyAccessibilityService">
...
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config" />
</service>
<?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" />
配置实现类
子类MyAccessibilityService继承AccessibilityService,并实现相应的重载方法:
方法 | 描述 |
---|---|
onServiceConnected() | 可选。系统会在成功连接上你的服务的时候调用这个方法,在这个方法里你可以做一下初始化工作,例如设备的声音震动管理,也可以调用setServiceInfo()进行配置工作 |
onAccessibilityEvent() | 通过这个函数可以接收系统发送来的AccessibilityEvent,接收来的AccessibilityEvent是经过过滤的,过滤是在配置工作时设置的。 |
onInterrupt() | 必须。这个在系统想要中断AccessibilityService返给的响应时会调用。在整个生命周期里会被调用多次。 |
onUnbind() | 可选。在系统将要关闭这个AccessibilityService会被调用。在这个方法中进行一些释放资源的工作 |
实操
onAccessibilityEvent()中对事件进行监听筛选
public void onAccessibilityEvent(AccessibilityEvent event) {
int eventType = event.getEventType();
switch (eventType) {
case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: //收到通知栏消息
break;
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: //界面状态改变
break;
case AccessibilityEvent.TYPE_VIEW_CLICKED: //点击事件
break;
case AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT: //文本改变
break;
//省略其他的一堆可以监听的事件
}
}
获取当前界面各种资源,信息
//获取根节点
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
//匹配Text获取节点
List<AccessibilityNodeInfo> list1 = rootNode.findAccessibilityNodeInfosByText("match_text");
//匹配id获取节点
List<AccessibilityNodeInfo> list2 = rootNode.findAccessibilityNodeInfosByViewId("match_id");
//获取子节点
AccessibilityNodeInfo infoNode = rootNode.getChild(index);
执行脚本操作
//模拟点击事件
target.performAction(AccessibilityNodeInfo.ACTION_CLICK);
//模拟输入内容
clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("label", "");
clipboard.setPrimaryClip(clip);
target.performAction(AccessibilityNodeInfo.ACTION_PASTE);
模拟Home,Back键
//后退键
performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
//Home键
performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME);
//模拟左滑
performGlobalAction(AccessibilityService.GESTURE_SWIPE_LEFT);
抢红包思路
1.监听微信应用发出的Notification,检查字段是否有“微信红包”字段;
2.点击Notification,进入微信界面
3.调用getRootInActiveWindow()获取根节点;
4.调用findAccessibilityNodeInfosByText(“领取红包”),获取该节点
5.调用performAction(AccessibilityNodeInfo.ACTION_CLICK)实现模拟点击
坑点
1.包被混淆,之前通过Android Device Monitor查看ID,然后根据findAccessibilityNodeInfosByID()去匹配节点,包被混淆之后每个版本不一样
2.很难找出没有文本的控件,如EditText,ImageView
private void findEditText(AccessibilityNodeInfo root) {
if (root.getClassName().equals("android.widget.EditText")) {
target = root;
} else {
for (int i = 0; i < root.getChildCount(); i++) {
if (root.getChildCount() != 0) {
findEditText(root.getChild(i));
}
}
}
}
3.锁屏抢红包要解除锁屏,isKeyguardLocked()方法错误理解。刚开始写代码的时候默认检测是否有锁屏,如果锁屏了调用disableKeyguard(),解锁,然后再检测是否真正解锁,成功解锁之后再进行抢红包的逻辑。后面发现disableKeyguard()并不是真正能够解锁,只是隐藏了锁屏。
km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
//得到锁管理器对象
boolean flag = km.isKeyguardLocked();
isFromNotification = true;
if (flag == true) {
kl = km.newKeyguardLock("unLock");
kl.disableKeyguard();
}
gotoWeCharUI(event);
官方对disableKeyguard()解释:
* Disable the keyguard from showing. If the keyguard is currently
* showing, hide it. The keyguard will be prevented from showing again
* until {@link #reenableKeyguard()} is called.