161 lines
5.1 KiB
Java
161 lines
5.1 KiB
Java
package com.rnbot;
|
|
|
|
import android.accessibilityservice.AccessibilityService;
|
|
import android.accessibilityservice.GestureDescription;
|
|
import android.graphics.Path;
|
|
import android.os.Bundle;
|
|
import android.view.accessibility.AccessibilityEvent;
|
|
import android.view.accessibility.AccessibilityNodeInfo;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
public class RNBotAccessibilityService extends AccessibilityService {
|
|
private static RNBotAccessibilityService instance;
|
|
|
|
public static RNBotAccessibilityService getInstance() {
|
|
return instance;
|
|
}
|
|
|
|
public static boolean isServiceRunning() {
|
|
return instance != null;
|
|
}
|
|
|
|
@Override
|
|
public void onAccessibilityEvent(AccessibilityEvent event) {
|
|
// 可以在这里监听各种事件
|
|
}
|
|
|
|
@Override
|
|
public void onInterrupt() {
|
|
// 服务中断
|
|
}
|
|
|
|
@Override
|
|
protected void onServiceConnected() {
|
|
super.onServiceConnected();
|
|
instance = this;
|
|
}
|
|
|
|
@Override
|
|
public void onDestroy() {
|
|
super.onDestroy();
|
|
instance = null;
|
|
}
|
|
|
|
public List<AccessibilityNodeInfo> findNodesByType(String type, String value) {
|
|
List<AccessibilityNodeInfo> result = new ArrayList<>();
|
|
AccessibilityNodeInfo root = getRootInActiveWindow();
|
|
if (root == null) return result;
|
|
|
|
switch (type) {
|
|
case "id":
|
|
findNodesByIdRecursive(root, value, result);
|
|
break;
|
|
case "text":
|
|
findNodesByTextRecursive(root, value, result);
|
|
break;
|
|
case "name":
|
|
findNodesByNameRecursive(root, value, result);
|
|
break;
|
|
case "className":
|
|
findNodesByClassNameRecursive(root, value, result);
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private void findNodesByIdRecursive(AccessibilityNodeInfo node, String resId, List<AccessibilityNodeInfo> result) {
|
|
if (node == null) return;
|
|
|
|
String id = node.getViewIdResourceName();
|
|
if (id != null && id.equals(resId)) {
|
|
result.add(node);
|
|
}
|
|
|
|
for (int i = 0; i < node.getChildCount(); i++) {
|
|
AccessibilityNodeInfo child = node.getChild(i);
|
|
if (child != null) {
|
|
findNodesByIdRecursive(child, resId, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void findNodesByTextRecursive(AccessibilityNodeInfo node, String text, List<AccessibilityNodeInfo> result) {
|
|
if (node == null) return;
|
|
|
|
CharSequence nodeText = node.getText();
|
|
if (nodeText != null && nodeText.toString().contains(text)) {
|
|
result.add(node);
|
|
}
|
|
|
|
for (int i = 0; i < node.getChildCount(); i++) {
|
|
AccessibilityNodeInfo child = node.getChild(i);
|
|
if (child != null) {
|
|
findNodesByTextRecursive(child, text, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void findNodesByNameRecursive(AccessibilityNodeInfo node, String name, List<AccessibilityNodeInfo> result) {
|
|
if (node == null) return;
|
|
|
|
CharSequence desc = node.getContentDescription();
|
|
if (desc != null && desc.toString().contains(name)) {
|
|
result.add(node);
|
|
}
|
|
|
|
for (int i = 0; i < node.getChildCount(); i++) {
|
|
AccessibilityNodeInfo child = node.getChild(i);
|
|
if (child != null) {
|
|
findNodesByNameRecursive(child, name, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void findNodesByClassNameRecursive(AccessibilityNodeInfo node, String className, List<AccessibilityNodeInfo> result) {
|
|
if (node == null) return;
|
|
|
|
CharSequence cls = node.getClassName();
|
|
if (cls != null && cls.toString().equals(className)) {
|
|
result.add(node);
|
|
}
|
|
|
|
for (int i = 0; i < node.getChildCount(); i++) {
|
|
AccessibilityNodeInfo child = node.getChild(i);
|
|
if (child != null) {
|
|
findNodesByClassNameRecursive(child, className, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean clickAt(int x, int y) {
|
|
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.N) {
|
|
return false;
|
|
}
|
|
|
|
Path path = new Path();
|
|
path.moveTo(x, y);
|
|
|
|
GestureDescription.Builder builder = new GestureDescription.Builder();
|
|
GestureDescription gesture = builder
|
|
.addStroke(new GestureDescription.StrokeDescription(path, 0, 50))
|
|
.build();
|
|
|
|
return dispatchGesture(gesture, null, null);
|
|
}
|
|
|
|
public boolean setTextById(String resId, String text) {
|
|
List<AccessibilityNodeInfo> nodes = findNodesByType("id", resId);
|
|
if (nodes.isEmpty()) return false;
|
|
|
|
AccessibilityNodeInfo node = nodes.get(0);
|
|
if (!node.isEditable()) return false;
|
|
|
|
Bundle arguments = new Bundle();
|
|
arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
|
|
return node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);
|
|
}
|
|
}
|