实现效果:html
实时监听当前聊天页面的最新一条消息,如图:java
实现原理:android
一样是利用AccessibilityService辅助服务,关于这个服务类还不了解的同窗能够先看下我上一篇关于抢红包的博客,原理都同样:微信
http://www.cnblogs.com/cxk1995/p/6363574.htmlide
1.首先咱们先来看一下微信聊天界面的布局,查看方法:布局
AndroidStudio--Tools--Android--Android Device Monitor,点击:this
2.如图咱们能够看到,其实每一条微信聊天记录都是一个RelativeLayout:htm
3.再往下看,咱们又能够发现,其实每个RelativeLayout下面,又包含了一个TextView,还有一个LinearLayout对象
TextView就是聊天的时间blog
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开启便可
写在最后:
我的兴趣研究,不建议用在非法途径上!!Demo想要的话留言我发给你嘻嘻....