Android几行代码实现实时监听微信聊天
实现效果:
实时监听当前聊天页面的最新一条消息,如图:
实现原理:
同样是利用AccessibilityService辅助服务,关于这个服务类还不了解的同学可以先看下我上一篇关于抢红包的博客,原理都一样:
http://www.cnblogs.com/cxk1995/p/6363574.html
1.首先我们先来看一下微信聊天界面的布局,查看方法:
AndroidStudio--Tools--Android--Android Device Monitor,点击:
2.如图我们可以看到,其实每一条微信聊天记录都是一个RelativeLayout:
3.再往下看,我们又可以发现,其实每一个RelativeLayout下面,又包含了一个TextView,还有一个LinearLayout
TextView就是聊天的时间
LinearLayout下则包含了我们所需要的聊天对象以及聊天信息,目前我们只需要这个就行了。
4.分析完后,我们思路就有了:
首先遍历获取每个RelativeLayout下的LinearLayout,因为该LinearLayout存在resource-id(com.tencent.mm:id/o),所以我们可以很容易可以获取到,然后我们再在LinearLayout中查找含有聊天对象(resource-id:com.tencent.mm:id/i_)以及聊天内容(resource-id:com.tencent.mm:id/ib)。
注:关于resource-id直接在上一步的查看布局下发可看到,因为resource-id随着版本的迭代可能会发生改变,所以也导致了一些不稳定因素。
核心代码
代码不多,也加了注释,直接看代码即可:
package com.cxk.wechatlog;
import android.accessibilityservice.AccessibilityService;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;
import java.util.List;
/**
* Created by cxk on 2017/2/4.
* email:471497226@qq.com
* <p>
* 获取即时微信聊天记录服务类
*/
public class WeChatLogService extends AccessibilityService {
/**
* 聊天对象
*/
private String ChatName;
/**
* 聊天最新一条记录
*/
private String ChatRecord = "test";
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
int eventType = event.getEventType();
switch (eventType) {
//每次在聊天界面中有新消息到来时都出触发该事件
case AccessibilityEvent.TYPE_VIEW_SCROLLED:
//获取当前聊天页面的根布局
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
//获取聊天信息
getWeChatLog(rootNode);
break;
}
}
/**
* 遍历
*
* @param rootNode
*/
private void getWeChatLog(AccessibilityNodeInfo rootNode) {
if (rootNode != null) {
//获取所有聊天的线性布局
List<AccessibilityNodeInfo> listChatRecord = rootNode.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/o");
if(listChatRecord.size()==0){
return;
}
//获取最后一行聊天的线性布局(即是最新的那条消息)
AccessibilityNodeInfo finalNode = listChatRecord.get(listChatRecord.size() - 1);
//获取聊天对象list(其实只有size为1)
List<AccessibilityNodeInfo> imageName = finalNode.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/i_");
//获取聊天信息list(其实只有size为1)
List<AccessibilityNodeInfo> record = finalNode.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/ib");
if (imageName.size() != 0) {
if (record.size() == 0) {
//判断当前这条消息是不是和上一条一样,防止重复
if (!ChatRecord.equals("对方发的是图片或者表情")) {
//获取聊天对象
ChatName = imageName.get(0).getContentDescription().toString().replace("头像", "");
//获取聊天信息
ChatRecord = "对方发的是图片或者表情";
Log.e("AAAA", ChatName + ":" + "对方发的是图片或者表情");
Toast.makeText(this, ChatName + ":" + ChatRecord, Toast.LENGTH_SHORT).show();
}
} else {
//判断当前这条消息是不是和上一条一样,防止重复
if (!ChatRecord.equals(record.get(0).getText().toString())) {
//获取聊天对象
ChatName = imageName.get(0).getContentDescription().toString().replace("头像", "");
//获取聊天信息
ChatRecord = record.get(0).getText().toString();
Log.e("AAAA", ChatName + ":" + ChatRecord);
Toast.makeText(this, ChatName + ":" + ChatRecord, Toast.LENGTH_SHORT).show();
}
}
}
}
}
/**
* 必须重写的方法:系统要中断此service返回的响应时会调用。在整个生命周期会被调用多次。
*/
@Override
public void onInterrupt() {
Toast.makeText(this, "我快被终结了啊-----", Toast.LENGTH_SHORT).show();
}
/**
* 服务开始连接
*/
@Override
protected void onServiceConnected() {
Toast.makeText(this, "服务已开启", Toast.LENGTH_SHORT).show();
super.onServiceConnected();
}
/**
* 服务断开
*
* @param intent
* @return
*/
@Override
public boolean onUnbind(Intent intent) {
Toast.makeText(this, "服务已被关闭", Toast.LENGTH_SHORT).show();
return super.onUnbind(intent);
}
}
使用方法:
设置-辅助功能-无障碍-点击WeChatLog开启即可
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架