基于 AccessibilityService 模拟辅助功能
https://github.com/sufadi/AccessibilityServiceMonitor
我们也可以使用adb 命令 adb shell am start com.eg.android.AlipayGphone/com.eg.android.AlipayGphone.AlipayLogin
/**
* 启动支付宝界面
* adb shell am start com.eg.android.AlipayGphone/com.eg.android.AlipayGphone.AlipayLogin
*/
public static void startAlipay(Context mContext) {
Intent intent = new Intent();
intent.setPackage("com.eg.android.AlipayGphone");
intent.setClassName("com.eg.android.AlipayGphone", "com.eg.android.AlipayGphone.AlipayLogin");
mContext.startActivity(intent);
}
这里的原理是:通过 findAccessibilityNodeInfosByText 找到蚂蚁森林的节点,但是这个节点clikebale 属性不可用,无法使用 AccessibilityNodeInfo.ACTION_CLICK,但是发现其父控件可以被点击,故对其父控件进行点击。
/**
* 自动点击进入蚂蚁森林界面
*/
public static void enterForestUI(AccessibilityNodeInfo nodeInfo) {
Log.d(Config.TAG, "enterForestUI ");
if (nodeInfo != null) {
// 找到界面中蚂蚁森林的文字
List list = nodeInfo.findAccessibilityNodeInfosByText("蚂蚁森林");
if (list == null) {
Log.d(Config.TAG, "enterForestUI finding no");
return;
} else {
Log.d(Config.TAG, "enterForestUI finding yes");
}
for (AccessibilityNodeInfo item : list) {
/**
* 蚂蚁森林本身不可点击,但是他的父控件可以点击
*/
AccessibilityNodeInfo parent = item.getParent();
if (null != parent && parent.isClickable()) {
parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
Log.d(Config.TAG, "item = " + item.toString() + ", parent click = " + parent.toString());
break;
}
}
}
}
能量球的button 事件 Button 的节点数据 text = null, descript = 4小时58分后才能收取, className = android.widget.Button, resId = null,匹配度比较低,故这里要防止误点击进入其他界面。
备注:好友的能量不能收取,因为支付宝在onTouch事件中return true,导致不会触发OnClick方法,但是支付宝中的蚂蚁森林可以收取自己的能量
public static void policy(AccessibilityNodeInfo nodeInfo, String packageName, String className) {
/**
* 蚂蚁森林界面
*/
if (packageName.equals("com.eg.android.AlipayGphone") &&
("com.alipay.mobile.nebulacore.ui.H5Activity".equals(className)
|| "com.uc.webkit.bf".equals(className))) {
if (nodeInfo != null) {
for (int i = 0; i < nodeInfo.getChildCount(); i++) {
AccessibilityNodeInfo child = nodeInfo.getChild(i);
if ("com.uc.webview.export.WebView".equals(child.getClassName())) {
Log.d(Config.TAG, "找到蚂蚁森林的 webView count = " + child.getChildCount());
findEveryViewNode(child);
break;
}
}
} else {
Log.d(Config.TAG, "alipayPolicy = null");
}
}
}
public static void findEveryViewNode(AccessibilityNodeInfo node) {
if (null != node && node.getChildCount() > 0) {
for (int i = 0; i < node.getChildCount(); i++) {
AccessibilityNodeInfo child = node.getChild(i);
// 有时 child 为空
if (child == null) {
continue;
}
//Log.d(TAG, "findEveryViewNode = " + child.toString());
String className = child.getClassName().toString();
if ("android.widget.Button".equals(className)) {
Log.d(Config.TAG, "Button 的节点数据 text = " + child.getText() + ", descript = " + child.getContentDescription() + ", className = " + child.getClassName() + ", resId = " + child.getViewIdResourceName());
boolean isClickable = child.isClickable();
boolean isResIdNull = child.getViewIdResourceName() == null ? true:false;
/**
* 好友的能量不能收取,因为支付宝在onTouch事件中return true,导致不会触发OnClick方法
*
* 但是支付宝中的蚂蚁森林可以收取自己的能量
*/
if ( isClickable && isResIdNull) {
child.performAction(AccessibilityNodeInfo.ACTION_CLICK);
Log.d(Config.TAG, "能量球 成功点击");
}
}
// 递归调用
findEveryViewNode(child);
}
}
}
运行日志
2018-08-22 14:21:28.560 24942-24942/? D/suhuazhi: 找到蚂蚁森林的 webView count = 1
2018-08-22 14:21:28.562 24942-24942/? D/suhuazhi: Button 的节点数据 text = null, descript = 4小时58分后才能收取, className = android.widget.Button, resId = null
2018-08-22 14:21:28.566 24942-24942/? D/suhuazhi: 能量球 成功点击
2018-08-22 14:21:28.571 24942-24942/? D/suhuazhi: Button 的节点数据 text = null, descript = 道具, className = android.widget.Button, resId = J_alter_game_tools
2018-08-22 14:21:28.577 24942-24942/? D/suhuazhi: Button 的节点数据 text = null, descript = 攻略, className = android.widget.Button, resId = J_alter_tips
2018-08-22 14:21:28.577 24942-24942/? D/suhuazhi: Button 的节点数据 text = null, descript = 消息, className = android.widget.Button, resId = J_message_entry
2018-08-22 14:21:28.578 24942-24942/? D/suhuazhi: Button 的节点数据 text = null, descript = 合种, className = android.widget.Button, resId = J_cooperation_entry