Xposed第四課(微信篇) 朋友圈點(diǎn)贊(2)之好友列表

前面做了個(gè)小玩意,朋友圈點(diǎn)贊伏恐,缺點(diǎn)是只能在當(dāng)前界面臨時(shí)顯示孩哑,并且不能選擇好友,返回后在進(jìn)去就沒(méi)有了翠桦,今天準(zhǔn)備將聯(lián)系人與朋友圈點(diǎn)贊功能關(guān)聯(lián)起來(lái)横蜒。

首先分析布局結(jié)構(gòu)


QQ截圖20180530204254.png

根據(jù)關(guān)鍵名稱進(jìn)行查找

BizContactEntranceView AlphabetScrollBar
QQ截圖20180530203817.png
QQ截圖20180530204400.png

定位到了com.tencent.mm.ui.contact.AddressUI

有人想,你光找到這個(gè)有個(gè)軟用销凑,數(shù)據(jù)庫(kù)你不找到怎么去保存到你自己的app里面丛晌。 大家接著往下看,可能我代碼有自己的想法斗幼,皮一下很開(kāi)心O(∩_∩)O

先上代碼

@Override
    public void hookContact() {
        XposedHelpers.findAndHookMethod("com.tencent.mm.ui.contact.AddressUI.a",
                mClassLoader,
                "coR",
                new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        super.afterHookedMethod(param);
                        Field oiy = XposedHelpers.findField(param.thisObject.getClass(), "oiy");
                        oiy.setAccessible(true);
                        LogUtils.i(oiy);
                        ListView oiyLv = (ListView) oiy.get(param.thisObject);
                        Class<?> mlvSuperClass = oiyLv.getClass().getSuperclass();
                        LogUtils.i(oiyLv);
                        XposedHelpers.findAndHookMethod(mlvSuperClass,
                                "setAdapter",
                                ListAdapter.class,
                                new XC_MethodHook() {
                                    @Override
                                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                                        super.beforeHookedMethod(param);
                                        final ListAdapter adapter = (ListAdapter) param.args[0];
                                        LogUtils.i(adapter.toString());
                                        XposedHelpers.findAndHookMethod(adapter.getClass(),
                                                "getView",
                                                int.class,
                                                View.class,
                                                ViewGroup.class,
                                                new XC_MethodHook() {
                                                    @Override
                                                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                                                        super.beforeHookedMethod(param);
                                                        int position = (int) param.args[0];
                                                        final View view = (View) param.args[1];
                                                        final ViewGroup viewGroup = (ViewGroup) param.args[2];
                                                        LogUtils.i(position, view, viewGroup, JSON.toJSONString(adapter.getItem(position)), adapter.getItem(position).toString());
                                                    }
                                                });
                                    }
                                });
                    }
                });
    }

可以得到以下信息

05-30 08:20:00.685 3223-3223/com.tencent.mm I/ContactImpl:  
    ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    │ main, com.zed.xposed.demo.action.inter.impl.ContactImpl$1.afterHookedMethod(ContactImpl.java:39)
    ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
    │ private android.widget.ListView com.tencent.mm.ui.contact.AddressUI$a.oiy
    └────────────────────────────────────────────────────────────────────────────────────────────────────────────────
     
    ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    │ main, com.zed.xposed.demo.action.inter.impl.ContactImpl$1.afterHookedMethod(ContactImpl.java:42)
    ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
    │ android.widget.ListView{10d02036 V.ED..CL ......ID 0,0-768,930 #7f10016e app:id/j8}
    └────────────────────────────────────────────────────────────────────────────────────────────────────────────────
05-30 08:20:01.066 3223-3223/com.tencent.mm I/ContactImpl:  
    ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    │ main, com.zed.xposed.demo.action.inter.impl.ContactImpl$1$1.beforeHookedMethod(ContactImpl.java:51)
    ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
    │ com.tencent.mm.ui.contact.a@2e2454f8
    └────────────────────────────────────────────────────────────────────────────────────────────────────────────────
05-30 08:20:01.102 3223-3223/com.tencent.mm I/ContactImpl:  
    ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    │ main, com.zed.xposed.demo.action.inter.impl.ContactImpl$1$1$1.beforeHookedMethod(ContactImpl.java:64)
    ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
    │ args[0] = 0
    │ args[1] = null
    │ args[2] = android.widget.ListView{10d02036 VFED..CL ......ID 0,0-768,930 #7f10016e app:id/j8}
    │ args[3] = {"fNU":49,"field_conRemark":"","field_deleteFlag":0,"field_descWordingId":"","field_nickname":"Aa 黃蓋","field_openImAppid":"","field_remarkDesc":"","field_showHead":65,"field_signature":"","field_username":"此處不顯示","field_verifyFlag":0,"field_weiboFlag":0,"key":"此處不顯示"}
    │ args[4] = com.tencent.mm.storage.f@1ac21e2a
    └────────────────────────────────────────────────────────────────────────────────────────────────────────────────
05-30 08:20:01.114 3223-3223/com.tencent.mm I/ContactImpl:  
    ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    │ main, com.zed.xposed.demo.action.inter.impl.ContactImpl$1$1$1.beforeHookedMethod(ContactImpl.java:64)
    ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
    │ args[0] = 1
    │ args[1] = null
    │ args[2] = android.widget.ListView{10d02036 VFED..CL ......ID 0,0-768,930 #7f10016e app:id/j8}
    │ args[3] = {"fNU":66,"field_conRemark":"","field_deleteFlag":0,"field_descWordingId":"","field_nickname":"aLOL-代練-小客服","field_openImAppid":"","field_remarkDesc":"","field_showHead":65,"field_signature":"想要LOL代練可以私聊","field_username":"此處不顯示","field_verifyFlag":0,"field_weiboFlag":0,"key":"此處不顯示"}
    │ args[4] = com.tencent.mm.storage.f@e76f385
    └────────────────────────────────────────────────────────────────────────────────────────────────────────────────

這是部分?jǐn)?shù)據(jù)澎蛛,我接下來(lái)要做的就是要一次性加載全部數(shù)據(jù)保存到自己的app 我們把上面的代碼少位改造下

  /**
     * 直接取得聯(lián)系人列表數(shù)據(jù)
     */
    @Override
    public void hookContact() {
        XposedHelpers.findAndHookMethod("com.tencent.mm.ui.contact.AddressUI.a",
                mClassLoader,
                "coR",
                new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        super.afterHookedMethod(param);
                        Field oiy = XposedHelpers.findField(param.thisObject.getClass(), "oiy");
                        oiy.setAccessible(true);
                        LogUtils.i(oiy);
                        ListView oiyLv = (ListView) oiy.get(param.thisObject);
                        Class<?> mlvSuperClass = oiyLv.getClass().getSuperclass();
                        LogUtils.i(oiyLv);
                        XposedHelpers.findAndHookMethod(mlvSuperClass,
                                "setAdapter",
                                ListAdapter.class,
                                new XC_MethodHook() {
                                    @Override
                                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                                        super.beforeHookedMethod(param);
                                        final ListAdapter adapter = (ListAdapter) param.args[0];
                                        LogUtils.i(adapter.toString());
                                        int count = adapter.getCount();
                                        for (int i = 0; i < count; i++) {
                                            WxContact contact = JSON.parseObject(JSON.toJSONString(adapter.getItem(i)), WxContact.class);
                                            WxContact ct = WxContactDB.queryByUsername(mContext, contact.getField_username());
                                            //先判斷是否已經(jīng)存在了 在進(jìn)行保存
                                            if (ct == null) {
                                                LogUtils.i(JSON.toJSONString(contact));
                                                WxContactDB.insertData(mContext, contact);
                                            }
                                        }
                                    }
                                });
                    }
                });
    }

然后與朋友長(zhǎng)按事件關(guān)聯(lián) 彈出一個(gè)聯(lián)系人列表 進(jìn)行選擇

改造后的代碼如下

 /**
     * hook 朋友圈
     */

    @Override
    public void hookWxMoments() {
        XposedHelpers.findAndHookMethod("com.tencent.mm.plugin.sns.ui.bb",
                mClassLoader,
                "onCreate",
                new XC_MethodHook() {
                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        super.afterHookedMethod(param);
                        Field mat = XposedHelpers.findFieldIfExists(param.thisObject.getClass(), "mActivity");
                        final Activity mActivity = (Activity) mat.get(param.thisObject);
                        Field odm = XposedHelpers.findFieldIfExists(param.thisObject.getClass(), "odm");
                        ListView mlv = (ListView) odm.get(param.thisObject);
                        Class<?> mlvSuperClass = mlv.getClass().getSuperclass();
                        XposedHelpers.findAndHookMethod(mlvSuperClass,
                                "setAdapter",
                                ListAdapter.class,
                                new XC_MethodHook() {
                                    @Override
                                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                                        super.beforeHookedMethod(param);
                                        final ListAdapter adapter = (ListAdapter) param.args[0];
                                        XposedHelpers.findAndHookMethod(adapter.getClass(),
                                                "getView",
                                                int.class,
                                                View.class,
                                                ViewGroup.class,
                                                new XC_MethodHook() {
                                                    @Override
                                                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                                                        super.beforeHookedMethod(param);
                                                        final View view = (View) param.args[1];
                                                        if (view != null) {
                                                            //fl 第一個(gè)view是圖片 第二個(gè)view是朋友圈內(nèi)容
                                                            final ViewGroup fl = (ViewGroup) view;
                                                            view.setOnLongClickListener(new View.OnLongClickListener() {

                                                                @Override
                                                                public boolean onLongClick(View v) {
                                                                    final List<WxContact> wxContacts = WxContactDB.queryAll(mContext);
                                                                    LogUtils.i(JSON.toJSONString(wxContacts));
                                                                    Dialog show = WxMomentContactDialog.instance(mActivity).build(wxContacts, new WxMomentContactDialog.CallBack() {
                                                                        @Override
                                                                        public void sure() {
                                                                            final StringBuffer sb = new StringBuffer();
                                                                            for (int i = 0; i < wxContacts.size(); i++) {
                                                                                WxContact contact = wxContacts.get(i);
                                                                                if (contact.isCheck()) {
                                                                                    sb.append(contact.getField_nickname());
                                                                                    sb.append(",");
                                                                                }
                                                                            }
                                                                            mActivity.runOnUiThread(new Runnable() {
                                                                                @Override
                                                                                public void run() {
                                                                                    String s = sb.toString();
                                                                                    if (fl != null && fl.getChildCount() > 1) {
                                                                                        LinearLayout msgLinear = (LinearLayout) fl.getChildAt(1);
                                                                                        for (int i = 0; i < msgLinear.getChildCount(); i++) {
                                                                                            View mc = msgLinear.getChildAt(i);
                                                                                            String resourceName = mContext.getResources().getResourceName(mc.getId());
                                                                                            if ("com.tencent.mm:id/de_".equals(resourceName)) {
                                                                                                ViewGroup vg = (ViewGroup) mc;
                                                                                                mc.setVisibility(View.VISIBLE);
                                                                                                if (vg.getChildCount() > 0) {
                                                                                                    TextView likeView = (TextView) vg.getChildAt(0);
                                                                                                    likeView.append(s);
                                                                                                } else {
                                                                                                    TextView tv = new TextView(mContext);
                                                                                                    tv.setText("");
                                                                                                    tv.append(",");
                                                                                                    tv.append(s);
                                                                                                    tv.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                                                                                                    vg.addView(tv);
                                                                                                }
                                                                                            }
                                                                                        }
                                                                                    }
                                                                                }
                                                                            });
                                                                        }
                                                                    });
                                                                    show.show();
                                                                    show.getWindow().setLayout(ViewUtil.dp2px(mActivity, 300f), ViewUtil.dp2px(mActivity, 400f));
                                                                    return false;
                                                                }
                                                            });
                                                        }
                                                    }
                                                });
                                    }
                                });
                    }
                });
    }

效果圖如下

效果一 效果二 效果三
微信截圖_20180601222733.png
微信截圖_20180601222659.png
微信截圖_20180601222713.png

有些不完美的地方,聯(lián)系人需要點(diǎn)擊下通訊錄才開(kāi)始保存數(shù)據(jù) 這個(gè)階段先做到聯(lián)系人與點(diǎn)贊關(guān)聯(lián)蜕窿,下次把點(diǎn)贊的聯(lián)系人與朋友圈消息關(guān)聯(lián)關(guān)系一起保存起來(lái)谋逻。就可以做到下次在進(jìn)去朋友圈可以看到上次點(diǎn)贊的。后面還可以進(jìn)行取消以及其他操作

垃圾代碼已上傳

這次我把我用到的微信版本和genymotion的arm-transfer放進(jìn)去了 所以體積變大了 哈哈

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末桐经,一起剝皮案震驚了整個(gè)濱河市斤贰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌次询,老刑警劉巖荧恍,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡送巡,警方通過(guò)查閱死者的電腦和手機(jī)摹菠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)骗爆,“玉大人次氨,你說(shuō)我怎么就攤上這事≌叮” “怎么了煮寡?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)犀呼。 經(jīng)常有香客問(wèn)我幸撕,道長(zhǎng),這世上最難降的妖魔是什么外臂? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任坐儿,我火速辦了婚禮,結(jié)果婚禮上宋光,老公的妹妹穿的比我還像新娘貌矿。我一直安慰自己,他們只是感情好罪佳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布逛漫。 她就那樣靜靜地躺著,像睡著了一般赘艳。 火紅的嫁衣襯著肌膚如雪尽楔。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,573評(píng)論 1 305
  • 那天第练,我揣著相機(jī)與錄音,去河邊找鬼玛荞。 笑死娇掏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的勋眯。 我是一名探鬼主播婴梧,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼客蹋!你這毒婦竟也來(lái)了塞蹭?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤讶坯,失蹤者是張志新(化名)和其女友劉穎番电,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡漱办,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年这刷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娩井。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡暇屋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出洞辣,到底是詐尸還是另有隱情咐刨,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布扬霜,位于F島的核電站定鸟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏畜挥。R本人自食惡果不足惜仔粥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蟹但。 院中可真熱鬧躯泰,春花似錦桂肌、人聲如沸忽刽。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)弦疮。三九已至乘瓤,卻和暖如春褂痰,著一層夾襖步出監(jiān)牢的瞬間念颈,已是汗流浹背兼搏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工卵慰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人佛呻。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓裳朋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親吓著。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鲤嫡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容