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 findNodesByType(String type, String value) { List 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 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 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 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 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 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); } }