基本信息
源码名称:android 读取微信聊天内容 示例源码(AccessibilityService)
源码大小:20.74M
文件格式:.zip
开发语言:Java
更新时间:2017-08-04
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):78630559
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
微信聊天界面的布局,查看方法:
AndroidStudio--Tools--Android--Android Device Monitor
public class WeChatLogService extends AccessibilityService {
/**
* 聊天对象
*/
private String ChatName;
/**
* 聊天最新一条记录
*/
private String ChatRecord = "cxk";
/**
* 小视频的秒数,格式为00:00
*/
private String VideoSecond;
@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/p");
if (listChatRecord.size() == 0) {
return;
}
//获取最后一行聊天的线性布局(即是最新的那条消息)
AccessibilityNodeInfo finalNode = listChatRecord.get(listChatRecord.size() - 1);
//获取聊天对象
GetChatName(finalNode);
//获取聊天内容
GetChatRecord(finalNode);
}
}
/**
* 遍历所有控件,找到头像Imagview,里面有对联系人的描述
*/
private void GetChatName(AccessibilityNodeInfo node) {
for (int i = 0; i < node.getChildCount(); i ) {
AccessibilityNodeInfo node1 = node.getChild(i);
if ("android.widget.ImageView".equals(node1.getClassName()) && node1.isClickable()) {
//获取聊天对象,这里两个if是为了确定找到的这个ImageView是头像的
if (!TextUtils.isEmpty(node1.getContentDescription())) {
ChatName = node1.getContentDescription().toString();
if (ChatName.contains("头像")) {
ChatName = ChatName.replace("头像", "");
}
}
}
GetChatName(node1);
}
}
/**
* 遍历所有控件:这里分四种情况
* 文字聊天: 一个TextView,并且他的父布局是android.widget.RelativeLayout
* 语音的秒数: 一个TextView,并且他的父布局是android.widget.RelativeLayout,但是他的格式是0"的格式,所以可以通过这个来区分
* 图片:一个ImageView,并且他的父布局是android.widget.FrameLayout,描述中包含“图片”字样(发过去的图片),发回来的图片现在还无法监听
* 表情:也是一个ImageView,并且他的父布局是android.widget.LinearLayout
* 小视频的秒数:一个TextView,并且他的父布局是android.widget.FrameLayout,但是他的格式是00:00"的格式,所以可以通过这个来区分
*
* @param node
*/
public void GetChatRecord(AccessibilityNodeInfo node) {
for (int i = 0; i < node.getChildCount(); i ) {
AccessibilityNodeInfo nodeChild = node.getChild(i);
//聊天内容是:文字聊天(包含语音秒数)
if ("android.widget.TextView".equals(nodeChild.getClassName()) && "android.widget.RelativeLayout".equals(nodeChild.getParent().getClassName().toString())) {
if (!TextUtils.isEmpty(nodeChild.getText())) {
String RecordText = nodeChild.getText().toString();
//这里加个if是为了防止多次触发TYPE_VIEW_SCROLLED而打印重复的信息
if (!RecordText.equals(ChatRecord)) {
ChatRecord = RecordText;
//判断是语音秒数还是正常的文字聊天,语音的话秒数格式为5"
if (ChatRecord.contains("\"")) {
Toast.makeText(this, ChatName "发了一条" ChatRecord "的语音", Toast.LENGTH_SHORT).show();
Log.e("WeChatLog",ChatName "发了一条" ChatRecord "的语音");
} else {
//这里在加多一层过滤条件,确保得到的是聊天信息,因为有可能是其他TextView的干扰,例如名片等
if (nodeChild.isLongClickable()) {
Toast.makeText(this, ChatName ":" ChatRecord, Toast.LENGTH_SHORT).show();
Log.e("WeChatLog",ChatName ":" ChatRecord);
}
}
return;
}
}
}
//聊天内容是:表情
if ("android.widget.ImageView".equals(nodeChild.getClassName()) && "android.widget.LinearLayout".equals(nodeChild.getParent().getClassName().toString())) {
Toast.makeText(this, ChatName "发的是表情", Toast.LENGTH_SHORT).show();
Log.e("WeChatLog",ChatName "发的是表情");
return;
}
//聊天内容是:图片
if ("android.widget.ImageView".equals(nodeChild.getClassName())) {
//安装软件的这一方发的图片(另一方发的暂时没实现)
if("android.widget.FrameLayout".equals(nodeChild.getParent().getClassName().toString())){
if(!TextUtils.isEmpty(nodeChild.getContentDescription())){
if(nodeChild.getContentDescription().toString().contains("图片")){
Toast.makeText(this, ChatName "发的是图片", Toast.LENGTH_SHORT).show();
Log.e("WeChatLog",ChatName "发的是图片");
}
}
}
}
//聊天内容是:小视频秒数,格式为00:00
if ("android.widget.TextView".equals(nodeChild.getClassName()) && "android.widget.FrameLayout".equals(nodeChild.getParent().getClassName().toString())) {
if (!TextUtils.isEmpty(nodeChild.getText())) {
String second = nodeChild.getText().toString().replace(":", "");
//正则表达式,确定是不是纯数字,并且做重复判断
if (second.matches("[0-9] ") && !second.equals(VideoSecond)) {
VideoSecond = second;
Toast.makeText(this, ChatName "发了一段" nodeChild.getText().toString() "的小视频", Toast.LENGTH_SHORT).show();
Log.e("WeChatLog","发了一段" nodeChild.getText().toString() "的小视频");
}
}
}
GetChatRecord(nodeChild);
}
}
/**
* 必须重写的方法:系统要中断此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);
}