概述
开发一个适配QQ 8.1.3的防撤回插件,并显示撤回通知。
原理
1. 防撤回
设置com.tencent.mobileqq.app.message.QQMessageFacade.a(ArrayList.class, boolean.class)
方法的返回值为空即可
1 | //在beforeHookedMethod中执行 |
2. 获取必要信息
上一个方法的第一个参数(ArrayList
)内容(toString
)形如:
1 | [RevokeMsgInfo[istroop= 1, shmsgseq= 356, frienduin= 1234568, fromuin= 12345678 msguid= 0, time= 1568796904, senduin= null, longmsgid= 0, longmsgcount=0 longmsgindex=0] |
当istroop
为1时,frienduin
是群号,否则为好友qq。
在某个版本后,toString
的结果中frienduin
被截断,所以解析字符串的方法行不通了。
可以通过反射来获取需要的字段值。
3. 显示撤回提示
这个功能的实现比较复杂,需要获取和生成一些类对象。
首先通过反射获取到QQAppInterface
实例(QQMessageFacade
的字段)
然后调用QQAppInterface.getCurrentAccountUin
方法获取自己的qq
再通过反射将RevokeMsgInfo
字段取出,为构造撤回提示做准备。
然后通过MessageRecordFactory
构造MessageRecord
。
然后使用ArrayList
将其打包。
最终调用com.tencent.mobileqq.app.message.QQMessageFacade.a(ArrayList.class, int.class)
方法来显示撤回提示。
具体可以参考QQ净化的防撤回实现。
4. 进行一些操作
过滤
判断是否为自己撤回的信息,如果是则不做处理。
获取群成员名
通过调用ContactUtils
的函数来获得。
为什么要适配
因为QQ版本不同,有些类名经过了混淆。
适配的关键在于找出混淆后的类名。
可反编译dex后,根据特征(字符串、函数参数、类结构等)查找smali。
防撤回功能涉及以下两个被混淆的类:
1 | String MessageRecordFactory = "avay"; |