version:1.6.6

fix:
update:微信电话直接从主页拨打
This commit is contained in:
2025-06-21 15:13:55 +08:00
parent 1c3b17e7c2
commit 9ecfa8de27
2 changed files with 130 additions and 17 deletions

View File

@@ -10,6 +10,8 @@ import android.content.IntentFilter;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.DisplayMetrics;
@@ -27,6 +29,8 @@ import com.xxpatx.os.config.CommonConfig;
import com.xxpatx.os.utils.ForegroundAppUtil;
import java.util.List;
import java.util.Optional;
import java.util.Random;
/**
* 通过微信标签最高支持8.0.498.0.50 获取不到数据
@@ -37,9 +41,12 @@ public class SelectToSpeakService extends AccessibilityService {
private MMKV mMMKV = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
private static final int ACTION_IME_ENTER_VERSION = 30;
private static final int ACTION_IME_ENTER_ID = 16908372;
private static final String DIALER_TEXT = "音视频通话";
private static final String CONTACT_TEXT = "通讯录";
private static final String SEARCH_TEXT = "搜索";
private static final String TAG_TEXT = "标签";
private static final String TAG_NAME = "孝心通";
private static final String MORE_NAME = "更多功能按钮,已折叠";
@@ -56,7 +63,7 @@ public class SelectToSpeakService extends AccessibilityService {
public static final int TYPE_VOICE = 0;
public static final int TYPE_VIDEO = 1;
private static final int WAIT_TIME = 1000;
private static final int WAIT_TIME = 1200;
private int mCallType = TYPE_VOICE;
@@ -101,7 +108,7 @@ public class SelectToSpeakService extends AccessibilityService {
} else {
mTagName = groupTag;
}
mCurrentStep = Step.CLICK_CONTACT;
mCurrentStep = Step.CLICK_HOME;
launchWeChat();
}
return super.onStartCommand(intent, flags, startId);
@@ -147,9 +154,9 @@ public class SelectToSpeakService extends AccessibilityService {
if (!TextUtils.isEmpty(currentClassName)) {
switch (currentClassName) {
case "com.tencent.mm.ui.LauncherUI":
if (mCurrentStep != Step.FIND_CONTACT) {
mCurrentStep = Step.CLICK_CONTACT;
}
// if (mCurrentStep != Step.FIND_CONTACT) {
// mCurrentStep = Step.CLICK_CONTACT;
// }
break;
case "com.tencent.mm.plugin.account.ui.WelcomeActivity":
case "com.tencent.mm.plugin.account.ui.LoginPasswordUI":
@@ -201,13 +208,30 @@ public class SelectToSpeakService extends AccessibilityService {
}
break;
case CLICK_HOME://主页能找到直接点击进去更多
stepHome(Property.TEXT, mName);
if (stepHome(Property.TEXT, mName)) {
Log.e(TAG, "_onAccessibilityEvent: not found contact in home");
} else {
clickViewById("com.tencent.mm:id/jha", Step.CLICK_SEARCH);
// step(Property.DESCRIPTION, SEARCH_TEXT, Step.CLICK_SEARCH);
}
break;
case CLICK_SEARCH:
putString(mName, Step.CLICK_SEARCH_CONTACT);
break;
case CLICK_SEARCH_CONTACT:
if (findSearchContact(Step.FIND_CONTACT)) {
findSearchContact(Property.TEXT, mName, Step.CLICK_QUICK_WECHAT_CALL);
} else {
Toaster.show("没有找到联系人");
}
break;
case CLICK_QUICK_WECHAT_CALL://点击更多页面
step(Property.DESCRIPTION, MORE_NAME, Step.CLICK_TARGET);
clickViewById("com.tencent.mm:id/bjz", Step.CLICK_TARGET);
// step(Property.DESCRIPTION, MORE_NAME, Step.CLICK_TARGET);
break;
case CLICK_TARGET://点击视频通话
stepCall(Property.TEXT, PARENT_VIDEO_TEXT);
// clickVideoCall();
break;
case CLICK_CONTACT://进入通讯录界面
@@ -218,13 +242,13 @@ public class SelectToSpeakService extends AccessibilityService {
}
break;
case FIND_CONTACT://模拟滑动找到联系人
findContact(Property.TEXT, mName, Step.CLICK_NAME);
findSearchContact(Property.TEXT, mName, Step.CLICK_QUICK_WECHAT_CALL);
break;
case FIND_TAG:
step(Property.TEXT, TAG_TEXT, Step.CLICK_TAG);
break;
case CLICK_TAG:
if (!step(Property.TEXT, mTagName, Step.CLICK_NAME)){
if (!step(Property.TEXT, mTagName, Step.CLICK_NAME)) {
Toaster.show("没有找到标签");
mCurrentStep = Step.WAITING;
}
@@ -347,6 +371,60 @@ public class SelectToSpeakService extends AccessibilityService {
}
}
private boolean findSearchContact(Step nextStep) {
List<AccessibilityNodeInfo> nodeInfos = findNodesByViewId("com.tencent.mm:id/gzf");
Log.e(TAG, "findSearchContact: " + nodeInfos);
Optional<AccessibilityNodeInfo> optional = nodeInfos.stream().findAny();
return optional.isPresent();
}
private void findSearchContact(Property type, String text, Step nextStep) {
List<AccessibilityNodeInfo> nodeInfos = findNodesByViewId("com.tencent.mm:id/odf");
Log.e(TAG, "findSearchContact: " + nodeInfos);
Optional<AccessibilityNodeInfo> optional = nodeInfos.stream().findAny();
if (optional.isPresent()) {
AccessibilityNodeInfo nodeInfo = optional.get();
clickNode(nodeInfo);
mCurrentStep = nextStep;
} else {
Toaster.show("没有找到联系人");
mCurrentStep = Step.WAITING;
}
}
private void putString(String text, Step nextStep) {
List<AccessibilityNodeInfo> nodeInfos = findNodesByViewId("com.tencent.mm:id/d98");
Optional<AccessibilityNodeInfo> optional = nodeInfos.stream().findAny();
if (optional.isPresent()) {
AccessibilityNodeInfo nodeInfo = optional.get();
Bundle args = new Bundle();
args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args);
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS); // 确保焦点在输入框
if (Build.VERSION.SDK_INT >= ACTION_IME_ENTER_VERSION) {
//see https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo.AccessibilityAction#ACTION_IME_ENTER
nodeInfo.performAction(ACTION_IME_ENTER_ID);
}
mCurrentStep = nextStep;
} else {
Toaster.show("没有找到搜索框");
mCurrentStep = Step.WAITING;
}
}
private void clickViewById(String id, Step nextStep) {
List<AccessibilityNodeInfo> nodeInfos = findNodesByViewId(id);
Optional<AccessibilityNodeInfo> optional = nodeInfos.stream().findAny();
if (optional.isPresent()) {
AccessibilityNodeInfo nodeInfo = optional.get();
clickNode(nodeInfo);
mCurrentStep = nextStep;
} else {
Toaster.show("没有找到搜索按钮");
}
}
private List<AccessibilityNodeInfo> findNodesByViewId(String id) {
List<AccessibilityNodeInfo> accessibilityNodeInfos = getRootInActiveWindow().findAccessibilityNodeInfosByViewId(id);
return accessibilityNodeInfos;
@@ -407,11 +485,11 @@ public class SelectToSpeakService extends AccessibilityService {
if (node != null) {
clickNode(node);
Log.e(TAG, "stepHome: mCurrentStep: " + mCurrentStep + " done");
mCurrentStep = mCurrentStep.next();
mCurrentStep = Step.CLICK_QUICK_WECHAT_CALL;
Log.e(TAG, "stepHome: next: " + mCurrentStep);
return true;
} else {
mCurrentStep = Step.CLICK_CONTACT;
mCurrentStep = Step.CLICK_SEARCH;
return false;
}
}
@@ -500,6 +578,14 @@ public class SelectToSpeakService extends AccessibilityService {
Log.e(TAG, "clickNode: e = " + e.getMessage());
}
if (node.isClickable()) {
//防检测机制:
//添加随机延迟(避免高频操作)
// handler.postDelayed(new Runnable() {
// @Override
// public void run() {
//
// }
// }, 1000 + new Random().nextInt(100));
boolean performAction = node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
Log.e(TAG, "clickNode: performAction = " + performAction);
if (!performAction) {
@@ -528,12 +614,13 @@ public class SelectToSpeakService extends AccessibilityService {
// }
}
@Deprecated
private boolean stepCall(Property type, String text) {
AccessibilityNodeInfo node = findNode(getRootInActiveWindow(), type, text);
if (node != null) {
Point point = getPointtByNode(node);
Log.e(TAG, "stepCall: " + point);
clickByPoint(point.x, point.y + 30);
clickByPoint(point.x, point.y);
// clickNode(node);
Log.e(TAG, "stepCall: mCurrentStep " + mCurrentStep + " done");
mCurrentStep = Step.CLICK_CALL;
@@ -545,6 +632,18 @@ public class SelectToSpeakService extends AccessibilityService {
}
}
private void clickVideoCall() {
List<AccessibilityNodeInfo> nodeInfos = findNodesByViewId("com.tencent.mm:id/a12");
Optional<AccessibilityNodeInfo> accessibilityNodeInfo = nodeInfos.stream().findAny();
if (accessibilityNodeInfo.isPresent()) {
AccessibilityNodeInfo nodeInfo = accessibilityNodeInfo.get();
clickNode(nodeInfo);
mCurrentStep = Step.CLICK_CALL;
} else {
Toaster.show("没有找到通话按钮");
}
}
private boolean stepAnswer(Property type, String text) {
AccessibilityNodeInfo node = findNode(getWindows(), type, text);
if (node != null) {
@@ -628,7 +727,9 @@ public class SelectToSpeakService extends AccessibilityService {
Path path = new Path();
path.moveTo(point.x, point.y);
GestureDescription.Builder builder = new GestureDescription.Builder();
builder.addStroke(new GestureDescription.StrokeDescription(path, 0, 200));
//防检测机制:
//添加随机延迟(避免高频操作)
builder.addStroke(new GestureDescription.StrokeDescription(path, 0, 200 + new Random().nextInt(100)));
GestureDescription gesture = builder.build();
boolean dispatched = dispatchGesture(gesture, new GestureResultCallback() {
@Override
@@ -694,16 +795,28 @@ public class SelectToSpeakService extends AccessibilityService {
private enum Step {
WAITING,
//微信免提
WECHAT_HANDS_FREE,
//电话免提
DIALER_HANDS_FREE,
//微信主页找用户名
CLICK_HOME,
//进入搜索界面
CLICK_SEARCH,
//是否弹出了联系人列表
CLICK_SEARCH_CONTACT,
//聊天界面+号
CLICK_QUICK_WECHAT_CALL,
//更多里面视频通话
CLICK_TARGET,
//主页点击导航栏通讯录
CLICK_CONTACT,
FIND_CONTACT,
CLICK_TAG,
//通讯录页面点击标签
FIND_TAG,
//点击对应的标签名
CLICK_TAG,
CLICK_NAME,
CLICK_INFO,