From ccd36149d1d70a0cbb9458f486d33fa893fcad6d Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Wed, 10 Sep 2025 19:59:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8B=A8=E5=8F=B7=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../selecttospeak/SelectToSpeakService.java | 173 ++++++++++-------- 1 file changed, 93 insertions(+), 80 deletions(-) diff --git a/app/src/main/java/com/google/android/accessibility/selecttospeak/SelectToSpeakService.java b/app/src/main/java/com/google/android/accessibility/selecttospeak/SelectToSpeakService.java index c509fc1..a37cb78 100644 --- a/app/src/main/java/com/google/android/accessibility/selecttospeak/SelectToSpeakService.java +++ b/app/src/main/java/com/google/android/accessibility/selecttospeak/SelectToSpeakService.java @@ -78,7 +78,7 @@ public class SelectToSpeakService extends AccessibilityService { private String mName = ""; private int mCallType = TYPE_VOICE; - private Procedure mCurrentProcedure = Procedure.WAITING; + private Strategy mCurrentStrategy = Strategy.WAITING; private boolean mAutoAccept = false; private Disposable mDisposable; @@ -125,7 +125,7 @@ public class SelectToSpeakService extends AccessibilityService { if (mContact != null) { mName = mContact.getName(); mCallType = mContact.getOperation(); - mCurrentProcedure = Procedure.CLICK_HOME; + mCurrentStrategy = Strategy.CLICK_HOME; launchWeChat(); } else { Toaster.showLong("没有获取到联系人数据"); @@ -157,12 +157,12 @@ public class SelectToSpeakService extends AccessibilityService { } private void checkClassName(AccessibilityEvent event) { - Log.e(TAG, "checkClassName: mCurrentStep = " + mCurrentProcedure); + Log.e(TAG, "checkClassName: mCurrentStep = " + mCurrentStrategy); if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { String currentPackageName = event.getPackageName().toString(); String currentClassName = event.getClassName().toString(); - switch (mCurrentProcedure) { + switch (mCurrentStrategy) { case WAITING: if (!TextUtils.isEmpty(currentPackageName) && "com.android.incallui".equals(currentPackageName)) { Log.e(TAG, "checkClassName: to dialer hands free"); @@ -180,7 +180,7 @@ public class SelectToSpeakService extends AccessibilityService { case "com.tencent.mm.plugin.account.ui.WelcomeActivity": case "com.tencent.mm.plugin.account.ui.LoginPasswordUI": Toaster.showLong("请先登录微信"); - mCurrentProcedure = Procedure.WAITING; + mCurrentStrategy = Strategy.WAITING; break; case "com.tencent.mm.plugin.label.ui.ContactLabelManagerUI": @@ -200,8 +200,8 @@ public class SelectToSpeakService extends AccessibilityService { * @param event */ private void parseAccessibilityEvent(AccessibilityEvent event) { - Log.e(TAG, "parseAccessibilityEvent: " + mCurrentProcedure); - switch (mCurrentProcedure) { + Log.e(TAG, "parseAccessibilityEvent: " + mCurrentStrategy); + switch (mCurrentStrategy) { case WAITING: mAutoAccept = mMMKV.decodeBool(CommonConfig.WECHAT_CALL_AUTO_ACCEPT_KEY, false); Log.e(TAG, "parseAccessibilityEvent: mAutoAccept = " + mAutoAccept); @@ -209,10 +209,10 @@ public class SelectToSpeakService extends AccessibilityService { return; } if (stepAnswer(Property.DESCRIPTION, RECEIVE_DESCRIPTION)) { - mCurrentProcedure = Procedure.WECHAT_HANDS_FREE; + mCurrentStrategy = Strategy.WECHAT_HANDS_FREE; Toast.makeText(this, "已自动接听视频/语音", Toast.LENGTH_LONG).show(); } else { - mCurrentProcedure = Procedure.WAITING; + mCurrentStrategy = Strategy.WAITING; // clickAnswer(); } break; @@ -223,29 +223,29 @@ public class SelectToSpeakService extends AccessibilityService { if (findHandsFree(Property.DESCRIPTION, DIALER_HANDS_FREE_CLOSE_TEXT)) { dialerHandsFree(Property.TEXT, DIALER_HANDS_FREE_TEXT); } else { - mCurrentProcedure = Procedure.WAITING; + mCurrentStrategy = Strategy.WAITING; } break; case CLICK_HOME://主页能找到直接点击进去更多 if (stepHome(Property.TEXT, mName)) { Log.e(TAG, "parseAccessibilityEvent: not found contact in home"); } else { - clickViewById("com.tencent.mm:id/jha", Procedure.CLICK_SEARCH); + clickViewById("com.tencent.mm:id/jha", Strategy.CLICK_SEARCH); // step(Property.DESCRIPTION, SEARCH_TEXT, Step.CLICK_SEARCH); } break; case CLICK_SEARCH: - putString(mName, Procedure.CLICK_SEARCH_CONTACT); + putString(mName, Strategy.CLICK_SEARCH_CONTACT); break; case CLICK_SEARCH_CONTACT: - if (findSearchContact(Procedure.FIND_CONTACT)) { - findSearchContact(Property.TEXT, mName, Procedure.CLICK_QUICK_WECHAT_CALL); + if (findSearchContact(Strategy.FIND_CONTACT)) { + findSearchContact(Property.TEXT, mName, Strategy.CLICK_QUICK_WECHAT_CALL); } else { Toaster.show("没有找到联系人"); } break; case CLICK_QUICK_WECHAT_CALL://点击更多页面 - clickViewById("com.tencent.mm:id/bjz", Procedure.CLICK_TARGET); + clickViewById("com.tencent.mm:id/bjz", Strategy.CLICK_TARGET); // step(Property.DESCRIPTION, MORE_NAME, Step.CLICK_TARGET); break; case CLICK_TARGET://点击视频通话 @@ -254,32 +254,32 @@ public class SelectToSpeakService extends AccessibilityService { break; case CLICK_CONTACT://进入通讯录界面 - if (stepHome(Property.TEXT, CONTACT_TEXT, Procedure.FIND_TAG)) { + if (stepHome(Property.TEXT, CONTACT_TEXT, Strategy.FIND_TAG)) { Log.e(TAG, "parseAccessibilityEvent: enter contact"); } else { touchContact(); } break; case FIND_CONTACT://模拟滑动找到联系人 - findSearchContact(Property.TEXT, mName, Procedure.CLICK_QUICK_WECHAT_CALL); + findSearchContact(Property.TEXT, mName, Strategy.CLICK_QUICK_WECHAT_CALL); break; case FIND_TAG: - step(Property.TEXT, TAG_TEXT, Procedure.CLICK_TAG); + step(Property.TEXT, TAG_TEXT, Strategy.CLICK_TAG); break; case CLICK_TAG: break; case CLICK_NAME://点击item - findContact(Property.TEXT, mName, Procedure.CLICK_INFO); + findContact(Property.TEXT, mName, Strategy.CLICK_INFO); break; case CLICK_INFO://进入个人信息页面 - stepCallDialog(Property.TEXT, DIALER_TEXT, Procedure.CLICK_CALL); + stepCallDialog(Property.TEXT, DIALER_TEXT, Strategy.CLICK_CALL); break; case CLICK_CALL://打视频或者电话 if (mCallType == TYPE_VIDEO) { - step(Property.TEXT, VIDEO_TEXT, Procedure.WAITING); + step(Property.TEXT, VIDEO_TEXT, Strategy.WAITING); } else if (mCallType == TYPE_VOICE) { - step(Property.TEXT, VOICE_TEXT, Procedure.WAITING); + step(Property.TEXT, VOICE_TEXT, Strategy.WAITING); } break; default: @@ -321,7 +321,19 @@ public class SelectToSpeakService extends AccessibilityService { } } - private boolean step(Property type, String text, Procedure nextProcedure) { + /** + * 打开这个界面可以直接选择联系人拨打 + */ + private void openVoip() { + Intent intent = new Intent(); + ComponentName component = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.contact.VoipAddressUI"); + intent.setComponent(component); + intent.putExtra("voip_video", false); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + + private boolean step(Property type, String text, Strategy nextStrategy) { AccessibilityNodeInfo node = findNode(getRootInActiveWindow(), type, text); if (node != null) { Rect rect = new Rect(); @@ -331,9 +343,9 @@ public class SelectToSpeakService extends AccessibilityService { return false; } clickNode(node); - Log.e(TAG, "step: mCurrentStep: " + mCurrentProcedure + " done"); - mCurrentProcedure = nextProcedure; - Log.e(TAG, "step: next: " + mCurrentProcedure); + Log.e(TAG, "step: mCurrentStep: " + mCurrentStrategy + " done"); + mCurrentStrategy = nextStrategy; + Log.e(TAG, "step: next: " + mCurrentStrategy); return true; } else { return false; @@ -341,7 +353,7 @@ public class SelectToSpeakService extends AccessibilityService { } // TODO: 2025/2/8 先把通讯录点击的换成node - private boolean stepHome(Property type, String text, Procedure nextProcedure) { + private boolean stepHome(Property type, String text, Strategy nextStrategy) { AccessibilityNodeInfo node = findNode(getWindows(), type, text); if (node != null) { Rect rect = new Rect(); @@ -351,9 +363,9 @@ public class SelectToSpeakService extends AccessibilityService { return false; } clickNode(node); - Log.e(TAG, "step: mCurrentStep: " + mCurrentProcedure + " done"); - mCurrentProcedure = nextProcedure; - Log.e(TAG, "step: next: " + mCurrentProcedure); + Log.e(TAG, "step: mCurrentStep: " + mCurrentStrategy + " done"); + mCurrentStrategy = nextStrategy; + Log.e(TAG, "step: next: " + mCurrentStrategy); return true; } else { return false; @@ -364,35 +376,35 @@ public class SelectToSpeakService extends AccessibilityService { private void touchContact() { boolean successful = clickByPoint(268, 1440); if (successful) { - mCurrentProcedure = Procedure.FIND_TAG; + mCurrentStrategy = Strategy.FIND_TAG; } else { - mCurrentProcedure = Procedure.WAITING; + mCurrentStrategy = Strategy.WAITING; Toaster.show("点击失败,请重试"); } } - private boolean findSearchContact(Procedure nextProcedure) { + private boolean findSearchContact(Strategy nextStrategy) { List nodeInfos = findNodesByViewId("com.tencent.mm:id/gzf"); Log.e(TAG, "findSearchContact: " + nodeInfos); Optional optional = nodeInfos.stream().findAny(); return optional.isPresent(); } - private void findSearchContact(Property type, String text, Procedure nextProcedure) { + private void findSearchContact(Property type, String text, Strategy nextStrategy) { List nodeInfos = findNodesByViewId("com.tencent.mm:id/odf"); Log.e(TAG, "findSearchContact: " + nodeInfos); Optional optional = nodeInfos.stream().findAny(); if (optional.isPresent()) { AccessibilityNodeInfo nodeInfo = optional.get(); clickNode(nodeInfo); - mCurrentProcedure = nextProcedure; + mCurrentStrategy = nextStrategy; } else { Toaster.show("没有找到联系人"); - mCurrentProcedure = Procedure.WAITING; + mCurrentStrategy = Strategy.WAITING; } } - private void putString(String text, Procedure nextProcedure) { + private void putString(String text, Strategy nextStrategy) { List nodeInfos = findNodesByViewId("com.tencent.mm:id/d98"); Optional optional = nodeInfos.stream().findAny(); if (optional.isPresent()) { @@ -406,20 +418,20 @@ public class SelectToSpeakService extends AccessibilityService { //see https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo.AccessibilityAction#ACTION_IME_ENTER nodeInfo.performAction(ACTION_IME_ENTER_ID); } - mCurrentProcedure = nextProcedure; + mCurrentStrategy = nextStrategy; } else { Toaster.show("没有找到搜索框"); - mCurrentProcedure = Procedure.WAITING; + mCurrentStrategy = Strategy.WAITING; } } - private void clickViewById(String id, Procedure nextProcedure) { + private void clickViewById(String id, Strategy nextStrategy) { List nodeInfos = findNodesByViewId(id); Optional optional = nodeInfos.stream().findAny(); if (optional.isPresent()) { AccessibilityNodeInfo nodeInfo = optional.get(); clickNode(nodeInfo); - mCurrentProcedure = nextProcedure; + mCurrentStrategy = nextStrategy; } else { Toaster.show("没有找到搜索按钮"); } @@ -449,15 +461,15 @@ public class SelectToSpeakService extends AccessibilityService { return null; } - private boolean stepCallDialog(Property type, String text, Procedure nextProcedure) { + private boolean stepCallDialog(Property type, String text, Strategy nextStrategy) { AccessibilityNodeInfo node = findNode(getRootInActiveWindow(), type, text); if (node != null) { Log.e(TAG, "stepCallDialog: isVisibleToUser: " + node.isVisibleToUser()); if (node.isVisibleToUser()) { clickNode(node); - Log.e(TAG, "stepCallDialog: mCurrentStep: " + mCurrentProcedure + " done"); - mCurrentProcedure = nextProcedure; - Log.e(TAG, "stepCallDialog: next: " + mCurrentProcedure); + Log.e(TAG, "stepCallDialog: mCurrentStep: " + mCurrentStrategy + " done"); + mCurrentStrategy = nextStrategy; + Log.e(TAG, "stepCallDialog: next: " + mCurrentStrategy); return true; } else { scrollDown(); @@ -467,7 +479,7 @@ public class SelectToSpeakService extends AccessibilityService { if (mFindCount == mMaxCount) { Log.e("stepCallDialog", "mCurrentStep: max"); Toast.makeText(this, "没有找到联系人", Toast.LENGTH_LONG).show(); - mCurrentProcedure = Procedure.WAITING; + mCurrentStrategy = Strategy.WAITING; mFindCount = 0; return false; } else { @@ -484,12 +496,12 @@ public class SelectToSpeakService extends AccessibilityService { AccessibilityNodeInfo node = findNode(getRootInActiveWindow(), type, text); if (node != null) { clickNode(node); - Log.e(TAG, "stepHome: mCurrentStep: " + mCurrentProcedure + " done"); - mCurrentProcedure = Procedure.CLICK_QUICK_WECHAT_CALL; - Log.e(TAG, "stepHome: next: " + mCurrentProcedure); + Log.e(TAG, "stepHome: mCurrentStep: " + mCurrentStrategy + " done"); + mCurrentStrategy = Strategy.CLICK_QUICK_WECHAT_CALL; + Log.e(TAG, "stepHome: next: " + mCurrentStrategy); return true; } else { - mCurrentProcedure = Procedure.CLICK_SEARCH; + mCurrentStrategy = Strategy.CLICK_SEARCH; return false; } } @@ -498,20 +510,20 @@ public class SelectToSpeakService extends AccessibilityService { private int mMaxCount = 5; - private boolean findContact(Property type, String text, Procedure nextProcedure) { + private boolean findContact(Property type, String text, Strategy nextStrategy) { AccessibilityNodeInfo node = findNode(getRootInActiveWindow(), type, text); if (node != null) { clickNode(node); - Log.e("findContact", "mCurrentStep: " + mCurrentProcedure + " done"); - mCurrentProcedure = nextProcedure; - Log.e("findContact", "next: " + mCurrentProcedure); + Log.e("findContact", "mCurrentStep: " + mCurrentStrategy + " done"); + mCurrentStrategy = nextStrategy; + Log.e("findContact", "next: " + mCurrentStrategy); mFindCount = 0; return true; } else { if (mFindCount == mMaxCount) { Log.e("findContact", "mCurrentStep: max"); Toast.makeText(this, "没有找到联系人", Toast.LENGTH_LONG).show(); - mCurrentProcedure = Procedure.WAITING; + mCurrentStrategy = Strategy.WAITING; mFindCount = 0; return false; } else { @@ -621,9 +633,9 @@ public class SelectToSpeakService extends AccessibilityService { Log.e(TAG, "stepCall: " + point); clickByPoint(point.x, point.y); // clickNode(node); - Log.e(TAG, "stepCall: mCurrentStep " + mCurrentProcedure + " done"); - mCurrentProcedure = Procedure.CLICK_CALL; - Log.e(TAG, "stepCall: next " + mCurrentProcedure); + Log.e(TAG, "stepCall: mCurrentStep " + mCurrentStrategy + " done"); + mCurrentStrategy = Strategy.CLICK_CALL; + Log.e(TAG, "stepCall: next " + mCurrentStrategy); return true; } else { Log.e(TAG, "stepCall: not found"); @@ -637,7 +649,7 @@ public class SelectToSpeakService extends AccessibilityService { if (accessibilityNodeInfo.isPresent()) { AccessibilityNodeInfo nodeInfo = accessibilityNodeInfo.get(); clickNode(nodeInfo); - mCurrentProcedure = Procedure.CLICK_CALL; + mCurrentStrategy = Strategy.CLICK_CALL; } else { Toaster.show("没有找到通话按钮"); } @@ -651,9 +663,9 @@ public class SelectToSpeakService extends AccessibilityService { clickByPoint(point.x, point.y - 50); clickByPoint(point.x, point.y); // clickNode(node); - Log.e(TAG, "stepAnswer: mCurrentStep " + mCurrentProcedure + " done"); - mCurrentProcedure = Procedure.WAITING; - Log.e(TAG, "stepAnswer: next " + mCurrentProcedure); + Log.e(TAG, "stepAnswer: mCurrentStep " + mCurrentStrategy + " done"); + mCurrentStrategy = Strategy.WAITING; + Log.e(TAG, "stepAnswer: next " + mCurrentStrategy); return true; } else { Log.e(TAG, "stepAnswer: not found"); @@ -668,9 +680,9 @@ public class SelectToSpeakService extends AccessibilityService { node.getBoundsInScreen(rect); Log.e(TAG, "dialerHandsFree: rect = " + rect); clickNode(node); - Log.e(TAG, "dialerHandsFree: mCurrentStep: " + mCurrentProcedure + " done"); - mCurrentProcedure = Procedure.WAITING; - Log.e(TAG, "dialerHandsFree: next: " + mCurrentProcedure); + Log.e(TAG, "dialerHandsFree: mCurrentStep: " + mCurrentStrategy + " done"); + mCurrentStrategy = Strategy.WAITING; + Log.e(TAG, "dialerHandsFree: next: " + mCurrentStrategy); return true; } else { return false; @@ -696,13 +708,13 @@ public class SelectToSpeakService extends AccessibilityService { clickByPoint(point.x, point.y - 50); clickByPoint(point.x, point.y); // clickNode(node); - Log.e(TAG, "handsFree: mCurrentStep " + mCurrentProcedure + " done"); - mCurrentProcedure = Procedure.WAITING; - Log.e(TAG, "handsFree: next " + mCurrentProcedure); + Log.e(TAG, "handsFree: mCurrentStep " + mCurrentStrategy + " done"); + mCurrentStrategy = Strategy.WAITING; + Log.e(TAG, "handsFree: next " + mCurrentStrategy); return true; } else { Log.e(TAG, "handsFree: not found"); - mCurrentProcedure = Procedure.WAITING; + mCurrentStrategy = Strategy.WAITING; return false; } } @@ -792,38 +804,39 @@ public class SelectToSpeakService extends AccessibilityService { return scrollScreen(0.5, 1.5); } - private enum Procedure { + private enum Strategy { WAITING, //微信免提 WECHAT_HANDS_FREE, //电话免提 DIALER_HANDS_FREE, - //微信主页找用户名 + + //1-1微信主页找用户名 CLICK_HOME, - //进入搜索界面 + //2-2进入搜索界面 CLICK_SEARCH, - //是否弹出了联系人列表 + //2-3是否弹出了联系人列表 CLICK_SEARCH_CONTACT, - //聊天界面+号 + //1-2 2-4聊天界面+号 CLICK_QUICK_WECHAT_CALL, - //更多里面视频通话 + //1-3 2-5更多里面视频通话 CLICK_TARGET, + /*1-4 语音通话*/ + CLICK_CALL, + + //主页点击导航栏通讯录 CLICK_CONTACT, - FIND_CONTACT, //通讯录页面点击标签 FIND_TAG, //点击对应的标签名 CLICK_TAG, - CLICK_NAME, CLICK_INFO, - - CLICK_CALL, CLICK_VIDEO_CALL; - private Procedure next() { + private Strategy next() { return values()[(this.ordinal() + 1) % values().length]; } }