Android 微信红包助手功能实现解析

本文详细描述了如何通过Android应用技术,如NotificationListenerService监听微信红包通知,解析通知内容,以及使用AccessibilityService模拟点击实现抢红包过程。重点讨论了难点和无障碍功能的运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

微信抢红包功能第一步是通过NotificationListenerService监听到红包通知,然后跳转到红包页面,最后通过辅助服务AccessibilityService来模拟点击动作,实现抢红包功能。技术难点主要是红包通知的判断和模拟点击的实现,模拟点击涉及到辅助服务相关技术。

此类实现有一个弊端,在微信的主页面上,收到消息的时候通知栏是不会通知的,所以这里不能进行解析通知栏跳转聊天页面。

在这里插入图片描述

1. 微信通知监听

AndroidManifest.xml中添加权限

 <uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"/>

在启动服务前,我们应该授予App监听系统通知的权限

startActivity(new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))

通知监听

private NotificationListenerService mListener = new NotificationListenerService() {
    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {
        //处理监听到的所有通知
        handleNotification(sbn);
    }
    @Override
    public void onNotificationRemoved(StatusBarNotification sbn) {
    }
};

注册监听

try {
    mListener.registerAsSystemService(mContext, new ComponentName(
            mContext.getPackageName(), getClass().getCanonicalName()),
            ActivityManager.getCurrentUser());
} catch (RemoteException e) {
    Log.e(TAG, "Cannot register listener", e);
}

注销监听

try {
    mListener.unregisterAsSystemService();
} catch (RemoteException e) {
    Log.e(TAG, "Cannot unregister listener", e);
}

2. 微信通知解析

通过NotificationListenerService监听通知,可以解析StatusBarNotification来获取微信红包的相关信息,可以获取通知来自的应用包名、通知的标题和内容、通知内容点击事件中包含的信息。

private void handleNotification(StatusBarNotification sbn) {
    Log.e("Hongbao", "StatusBarNotification sbn: " + sbn);
    //StatusBarNotification: StatusBarNotification(pkg=com.tencent.mm user=UserHandle{0} id=1753384416 tag=null key=0|com.tencent.mm|1753384416|null|10162: Notification(channel=message_channel_new_id shortcut=null 
    //StatusBarNotification中包含很多信息,主要是getPackageName和getNotification
    final String packageName = sbn.getPackageName();
    //过滤微信包名
    if ("com.tencent.mm".equals(packageName)) {
        android.app.Notification notification = sbn.getNotification();
        //获取通知标题和内容信息
        Bundle extras = notification.extras;
        String title = extras.getString(android.app.Notification.EXTRA_TITLE);
        String content = extras.getString(android.app.Notification.EXTRA_TEXT);
        
        //获取通知时间
        long when = notification.when;
        
        //通知的点击Intent:包含重要信息
        PendingIntent contentIntent = notification.contentIntent;
        Intent intent = contentIntent.getIntent();
        if (intent != null && intent.getExtras() != null) {
            Bundle info = intent.getExtras();
            //包含2个重要的Key:
            //Main_User,可用来区分是否是群红包还是个人红包,群红包带有`@chatroom`关键字
            //MainUI_User_Last_Msg_Type,可用来判断消息类型,红包类型值为:436207665
            for (String key : info.keySet()) {
                Object value = info.get(key);
                Log.e("Hongbao", "contentIntent key=" + key + " value=" + value);
            }
            int msgType = info.getInt("MainUI_User_Last_Msg_Type");
            String wechatId = info.getString("Main_User");
            Log.e("Hongbao", "contentIntent msgType=" + msgType + " isHongbaoType=" + (msgType == 436207665) + " wechatId=" + wechatId + " isGroupMessage=" + wechatId.contains("@chatroom"));
        }
        //判断是否为红包类型:主要是解析通知内容是否包含[微信红包]关键字及消息类型,还可以过滤出发消息的人
        String from;
        String message = content;
        Matcher matcher = Pattern.compile("^\\\\[(.*?)\\\\](.*?):(.*)").matcher(content);
        if (matcher.find()) {
            from = matcher.group(2);
            message = matcher.group(3);
        } else {
            if (message.contains(":")) {
                from = message.split(":")[0];
            } else {
                from = title;
            }
        }
        Log.e("Hongbao", "title=" + title + " content=" + content + " isHongbao=" + content.contains("[微信红包]"));
        Log.e("Hongbao", "from=" + from + " message=" + message);
    }
}

根据代码打印出以下日志:

// 个人红包
04-28 16:35:35.439 31491 31491 E Hongbao : StatusBarNotification sbn: StatusBarNotification(pkg=com.tencent.mm user=UserHandle{0} id=1753384416 tag=null key=0|com.tencent.mm|1753384416|null|10162: Notification(channel=message_channel_new_id shortcut=null contentView=null vibrate=null sound=null tick defaults=0x0 flags=0x11 color=0x00000000 category=msg vis=PRIVATE))
04-28 16:35:35.442 31491 31491 E Hongbao : contentIntent key=talkerCount value=1
04-28 16:35:35.442 31491 31491 E Hongbao : contentIntent key=nofification_type value=new_msg_nofification
04-28 16:35:35.442 31491 31491 E Hongbao : contentIntent key=MainUI_FromFinderNotification value=false
04-28 16:35:35.442 31491 31491 E Hongbao : contentIntent key=MainUI_User_Last_Msg_BgNotify_From value=initIntent
04-28 16:35:35.442 31491 31491 E Hongbao : contentIntent key=MainUI_User_Last_Msg_Type value=436207665
04-28 16:35:35.442 31491 31491 E Hongbao : contentIntent key=Intro_Is_Muti_Talker value=false
04-28 16:35:35.442 31491 31491 E Hongbao : contentIntent key=Main_User value=wxid_6yla0e502e7812
04-28 16:35:35.442 31491 31491 E Hongbao : contentIntent msgType=436207665 isHongbaoType=true wechatId=wxid_6yla0e502e7812 isGroupMessage=false
04-28 16:35:35.443 31491 31491 E Hongbao : title=Maxx content=[微信红包] 恭喜发财,大吉大利 isHongbao=true
04-28 16:35:35.443 31491 31491 E Hongbao : from=Maxx message=[微信红包] 恭喜发财,大吉大利

// 群红包
04-28 16:36:40.302 31491 31491 E Hongbao : StatusBarNotification sbn: StatusBarNotification(pkg=com.tencent.mm user=UserHandle{0} id=-184157365 tag=null key=0|com.tencent.mm|-184157365|null|10162: Notification(channel=message_channel_new_id shortcut=null contentView=null vibrate=null sound=null tick defaults=0x0 flags=0x11 color=0x00000000 category=msg vis=PRIVATE))
04-28 16:36:40.302 31491 31491 E Hongbao : contentIntent key=talkerCount value=1
04-28 16:36:40.302 31491 31491 E Hongbao : contentIntent key=nofification_type value=new_msg_nofification
04-28 16:36:40.302 31491 31491 E Hongbao : contentIntent key=MainUI_FromFinderNotification value=false
04-28 16:36:40.302 31491 31491 E Hongbao : contentIntent key=MainUI_User_Last_Msg_BgNotify_From value=initIntent
04-28 16:36:40.303 31491 31491 E Hongbao : contentIntent key=MainUI_User_Last_Msg_Type value=436207665
04-28 16:36:40.303 31491 31491 E Hongbao : contentIntent key=Intro_Is_Muti_Talker value=false
04-28 16:36:40.303 31491 31491 E Hongbao : contentIntent key=Main_User value=34464526055@chatroom
04-28 16:36:40.303 31491 31491 E Hongbao : contentIntent msgType=436207665 isHongbaoType=true wechatId=34464526055@chatroom isGroupMessage=true
04-28 16:36:40.303 31491 31491 E Hongbao : title=Paul、Maxx content=Maxx: [微信红包] 恭喜发财,大吉大利 isHongbao=true
04-28 16:36:40.303 31491 31491 E Hongbao : from=Maxx message=Maxx: [微信红包] 恭喜发财,大吉大利

3. 无障碍功能模拟点击

当完成微信通知的解析后,如果是微信红包,则可以直接跳转到相应的聊天对话框

notification.contentIntent.send();

后续就通过AccessibilityService 无障碍功能模拟点击打开红包和拆开红包功能。

添加AccessibilityService服务

<service
    android:name=".service.HongbaoAccessibilityService"
    android:enabled="true"
    android:exported="true"
    android:label="@string/accessibility_name"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/hongbao_service_config" />
</service>

添加AccessibilityService配置信息

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/accessibility_description"
    android:accessibilityEventTypes="typeAllMask"
    android:packageNames="com.tencent.mm"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:notificationTimeout="100"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"/>

前往开启辅助服务界面

public void goAccess() {
    Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    mContext.startActivity(intent);
}

模拟点击事件

public void performViewClick(AccessibilityNodeInfo nodeInfo) {
    if (nodeInfo == null) {
        return;
    }
    while (nodeInfo != null) {
        if (nodeInfo.isClickable()) {
            nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            break;
        }
        nodeInfo = nodeInfo.getParent();
    }
}

查找对应文本的View

public AccessibilityNodeInfo findViewByText(String text) {
    return findViewByText(text, false);
}

/**
 * 查找对应文本的View
 *
 * @param text  text
 * @param clickable 该View是否可以点击
 * @return View
 */
public AccessibilityNodeInfo findViewByText(String text, boolean clickable) {
    AccessibilityNodeInfo accessibilityNodeInfo = getRootInActiveWindow();
    if (accessibilityNodeInfo == null) {
        return null;
    }
    List<AccessibilityNodeInfo> nodeInfoList = accessibilityNodeInfo.findAccessibilityNodeInfosByText(text);
    if (nodeInfoList != null && !nodeInfoList.isEmpty()) {
        for (AccessibilityNodeInfo nodeInfo : nodeInfoList) {
            if (nodeInfo != null && (nodeInfo.isClickable() == clickable)) {
                return nodeInfo;
            }
        }
    }
    return null;
}

4.相关参考

[1] Android通知还能这么玩?

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值