first blood
This commit is contained in:
160
android/src/main/java/com/rnbot/RNBotAccessibilityService.java
Normal file
160
android/src/main/java/com/rnbot/RNBotAccessibilityService.java
Normal file
@@ -0,0 +1,160 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user