前言
上篇文章讲解了调Xposed代码的时机。
有不少同学给我说,数据库的hook和免重启的方案不太明白,我私下也给这些同学详细解释了一遍。
其实我也是借鉴了许多优秀的项目,还有好多大牛提供的思路。
我自己也走了不少弯路,总结出了几点经验技巧吧,也谈不上太高端,都是比较简单的例子。
我发帖子的初衷也是让刚接触Xposed的同学少走一些弯路。
那么这篇文章,大多也是借鉴了一些优秀的文章和demo,也包括我自己的一些思路。
大家不懂的地方一定要留言, 我会详细给大家解释(不要问我百度能查到的),这样一方面提高我自己的写作经验,一方面帮助大家快速入门。
这篇文章实现的功能是:利用微信的群发助手,按标签群发消息。(可以在文章最后先看一下实现效果)
一、通过Activity的跳转事件,hook出所传的参数
先看以下代码:
[Java] 纯文本查看 复制代码 findAndHookMethod(
"android.app.Activity", pkg.loader,
"startActivity", C.Intent, object : XC_MethodHook() {
@Throws(Throwable::class)
override fun beforeHookedMethod(param: MethodHookParam) {
val intent = param.args[0] as Intent?
if (isActivityTest) {
LogTool.e("activity_log---->Activity.startActivity => " +
"${param.thisObject.javaClass}, " +
"intent => ${bundleToString(intent?.extras)}")
}
}
})
这样界面跳转的时候,就hook到了。所以我们打开群发助手的界面,去实际操作一下。
点下一步的时候 logcat中看看会hook到什么。以下是logcat中打印的日志。建议不要在Xposed软件中打印日志(本人是不习惯这样做)。
跳转界面的时候会传mass_send_contact_list = wxid_6rh4uc9xww6z22;wxid_808ce6sfkmwl22
看到wxid用分号隔开了。我们在合适的时机去调startActivity方法,传相应的mass_send_contact_list参数就可以了。
二、查找数据库结构,找出标签的信息
我们要传的wxid集合,得是某一个标签下的,所以得获取标签列表和标签下的好友。
有两种方法获取标签信息。一是找出获取的源码,用xposed调用。二是通过微信本地数据库获取。
我觉得第二种更好,不用版本适配,做起来也相对简单一点。
通过分析数据库表,得到以下信息:
标签的列表信息在ContactLabel表中
标签下的好友在rcontact表中的contactLabelIds中。 rcontact是好友信息的表,contactLabelIds是好友对应的标签,ContactLabel中的labelID,以逗号隔开。
三、对数据库进行“查”的操作
比如我们要查,“标签测试1”下的好友的wxid,以分号隔开。请看以下代码
[Java] 纯文本查看 复制代码 fun queryLabelID(labelName:String):String{
val database = MainDatabase.mainDB ?: return ""
val sql = "select labelID from ContactLabel where labelName = '$labelName'"
var cursor: Any? = null
try {
cursor = XposedHelpers.callMethod(database, "rawQuery", sql, null)
val count = XposedHelpers.callMethod(cursor, "getCount") as Int
(0 until count).map {
XposedHelpers.callMethod(cursor, "moveToNext")
val labelID = XposedHelpers.callMethod(cursor, "getString", 0) as String
return queryRContact(labelID)
}
} catch (e: Exception) {
} finally {
if (cursor != null) {
XposedHelpers.callMethod(cursor, "close")
}
}
return ""
}
fun queryRContact(labelID: String):String{
val database = MainDatabase.mainDB ?: return ""
val sql = "select contactLabelIds,username from rcontact"
var cursor: Any? = null
var wxids = ""
try {
cursor = XposedHelpers.callMethod(database, "rawQuery", sql, null)
val count = XposedHelpers.callMethod(cursor, "getCount") as Int
(0 until count).map {
XposedHelpers.callMethod(cursor, "moveToNext")
val contactLabelIds = XposedHelpers.callMethod(cursor, "getString", 0) as String
val username = XposedHelpers.callMethod(cursor, "getString", 1) as String
val array = contactLabelIds.split(",")
if (array.contains(labelID)){
wxids = "$wxids;$username"
}
}
return wxids.substring(1,wxids.length)
} catch (e: Exception) {
} finally {
if (cursor != null) {
XposedHelpers.callMethod(cursor, "close")
}
}
return ""
}
我们调用queryLabelID("标签测试1") ,就return到了相应的字符串了。
四、调方法的合适时机
我觉得最好的思路就是在微信中加一个控件,点击展示标签列表,让用户自己选择要转发的标签。
其中,在微信中加载本地的布局文件用到了XModuleResources,文章最后会给源码,大家熟悉一下获取过程,我不做讲解。
注意:查数据库的操作写到子线程中,为了防止UI卡顿。
以下是实现效果:
源码下载地址:https://github.com/syxxjujing/Assistant
源码中还有朋友圈一键转发的功能,是从微信巫师中直接copy下来的,大家也可以学习一下。
欢迎大家给我留言!写的不足的地方,还请大佬们指点。 |