工具:android studio ,Android Device Monitor(在安卓sdk目录下的tool目录下有一个monitor.bat文件,点击启动)
第一步:创建安卓应用。
目录结构:
wechat.xml
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagReportViewIds|flagRetrieveInteractiveWindows"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true"
android:description="@string/wechat"
android:notificationTimeout="100"
android:packageNames="com.tencent.mm"
></accessibility-service>
? ? android:packageNames="com.tencent.mm"指监听的应用包名,多个逗号隔开。
创建service并实现里面的两个方法
public class weChatService extends AccessibilityService {
}
?在AndroidManifest.xml中注册service
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.example.myapplication.weChatService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService"/>
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/wechat"/>
</service>
</application>
</manifest>
使用monitor获取界面元素的id
第一步:把手机显示的界面加载过来

在界面上点击元素,右边就可以看见该元素的结构和id

?代码:
在刚刚实现的代码中的写自己的逻辑
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
int eventType = event.getEventType();
可以通过eventtype判断界面的事件,这个可以百度搜一下AccessibilityEvent
我这边没有判断直接在里面写代码,首先是通过
AccessibilityNodeInfo rootInfo = getRootInActiveWindow();
?方法拿到界面所有的元素,然后通过方法搜索元素
findByID(rootInfo, "com.tencent.mm:id/bxz",0);
private void findByID(AccessibilityNodeInfo rootInfo, String text,int type) {
if(rootInfo==null){
return;
}
if (rootInfo.getChildCount() > 0) {
for (int i = 0; i < rootInfo.getChildCount(); i++) {
AccessibilityNodeInfo child = rootInfo.getChild(i);
try {
if (child.findAccessibilityNodeInfosByViewId(text).size() > 0) {
for (AccessibilityNodeInfo info : child.findAccessibilityNodeInfosByViewId(text)) {
if(type==0){
//在输入框输入111111.....
changeInput(info,"1111111111111111111");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
findByID(getRootInActiveWindow(), "com.tencent.mm:id/hdm",1);
}else if(type == 1){
//输入框的点击事件
getClickable(info).performAction(AccessibilityNodeInfo.ACTION_CLICK);
}else if(type == 2){
//获取元素的文字信息
System.out.println("昵称"+info.getText().toString());
}else if(type ==3){
System.out.println("地区"+info.getText().toString());
findByID(getRootInActiveWindow(), "com.tencent.mm:id/ei",4);
}else if(type ==4){
//点击事件
getClickable(info).performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
}
}
} catch (NullPointerException e) {
}
findByID(child, text,type);//递归一直找一层层的全部遍历
}
}
}
//有些节点不可点击 点击交给父级甚至父级的父级...来做的。
private AccessibilityNodeInfo getClickable(AccessibilityNodeInfo info) {
// Log.i(TAG, info.getClassName() + ": " + info.isClickable());
if (info.isClickable()) {
return info;//如果可以点击就返回
} else {//不可点击就检查父级 一直递归
return getClickable(info.getParent());
}
}
private void changeInput(AccessibilityNodeInfo info,String text) { //改变editText的内容
Bundle arguments = new Bundle();
arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE,
text);
info.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
}
代码很乱,只是简单测试用。可以通过这种方式实现一些app的自动化操作或脚本。另外其中有部分方法也是百度搜索拼接起来的。
|