1. Java

微信自动接听助手-WeChatAutoAnswer

因为以前使用的自动接听助手长期不更新已经不适配最新的微信版本(7.0.13)了。怨人不如自怨,求诸人不如求之己,所以决定自己来写一个微信自动接听助手。于是就有了今天的WeChatAutoAnswer !

–>使用手冊和下載地址<–

那么就来看一下实(踩)现(坑)过程:首先我们学习一下AccessibilityService(使用搜索引擎就能找到许多入门教程),这里我就不多赘述了。简单说就是通过AccessibilityService这个功能实现对微信应用的监听如果发现有视频通话请求就模拟点击接通即可。

1.1首先在manifest中注册一个service

<service android:name=".WeChatAccessibilityService"
            android:label="@string/app_name"
            android:exported="true"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
            android:process=":BackgroundService">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService" />
            </intent-filter>
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/accessible_service_config_ali" />
        </service>

文件:xml/accessible_service_config_ali.xml

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged|typeNotificationStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagReportViewIds|flagRetrieveInteractiveWindows"
    android:canRetrieveWindowContent="true"
    android:notificationTimeout="64"
    android:description="@string/desc"
    android:canPerformGestures="true"
    android:packageNames="com.tencent.mm" />

1.2然后写一个类继承AccessibilityService即可

package top.sencom.wechatautoanswer;

import android.accessibilityservice.AccessibilityService;
import android.annotation.SuppressLint;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;


public class WeChatAccessibilityService extends AccessibilityService {


    private static final String TAG = "WeChatAccessibilityService";

    @SuppressLint("LongLogTag")
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        String pkgName = event.getPackageName().toString();
        int eventType = event.getEventType();
        Log.d(TAG, "onAccessibilityEvent:event:"+eventType);
        switch (eventType) {
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                 try{
                    AccessibilityNodeInfo info = event.getSource();
                    String className = event.getClassName().toString();
                    if(className.equals("com.tencent.mm.plugin.voip.ui.VideoActivity")){
                        autoAnswer();
                    }
                    Log.d(TAG,"CLASSNAME:"+ className);
                }catch (Exception exx){
                    exx.printStackTrace();
                }

        }
    }

    @SuppressLint("LongLogTag")
    private void autoAnswer() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo != null) {
            int child = nodeInfo.getChildCount();
            // iterate through all child of parent view
            int imCount = 0;
            for (int i=0; i<child; i++){
                AccessibilityNodeInfo childNodeView = nodeInfo.getChild(i);
                if(childNodeView.getClassName().toString().equals("android.widget.ImageView")){
                    if (imCount == 0 || imCount ==1){
                        imCount++;
                        continue;
                    }
                    childNodeView.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                  break;
                }
                Log.d(TAG,"childNodeView:"+childNodeView.getClassName());
                // Do something with this window content
            }
        }
    }
    @Override
    public void onInterrupt() {

    }
}

这里我们在监听器里面监听AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED如果有窗口状态改变且切换到

com.tencent.mm.plugin.voip.ui.VideoActivity(怎么得到这个类名的?这里我通过adb命令查看当前显示的activity获得的)这个Acitvity时我们就可以调用 autoAnswer();方法然后在里面找到接听按钮点下去就OK

光看autoAnswer()你可能会一头雾水,这里我制作了一个截图。通过代码可以看出我遍历整个子控件然后模拟点击了第三个android.widget.ImageView。那么为什么是第三个?我主要使用Log打印日志一个一个试出来的。

转语音childNodeView:android.widget.ImageView
childNodeView:android.widget.TextView
挂断childNodeView:android.widget.ImageView
childNodeView:android.widget.TextView
接听childNodeView:android.widget.ImageView
childNodeView:android.widget.TextView
缩小childNodeView:android.widget.Button
childNodeView:android.widget.TextView

通过对日志的分析,找出了第一个imageview是图中的绿色区域控件即转语音;第二个imageview是黄色区域的挂断,第三个imageview那个就是我们所需要的接听控件。这里为什么要自找控件位置主要是用uiautomatorviewer和DDMS 都不能分析上图界面的布局(报错)

Error obtaining UI hierarchy
Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException: Remote object doesn't exist!

下载地址:

1.http://home.sencom.top:8080/apps/WeChatAutoAnswer-2020-05-03.apk

2.https://pan.baidu.com/s/1hcuOCx6CILIe70NPDornxg 提取码:tc15