編譯插樁是指在代碼編譯期間修改或新增代碼
可以?xún)蓚€(gè)地方進(jìn)行編譯插樁
1誊薄、java編譯為class時(shí)
APT、AndroidAnnotation 等就是在此處觸發(fā)代碼生成
2、.class進(jìn)一步轉(zhuǎn)為.dex時(shí)
一般情況下设江,我們經(jīng)常會(huì)使用編譯插樁實(shí)現(xiàn)如下幾種功能:
日志埋點(diǎn)锦茁;
性能監(jiān)控;
動(dòng)態(tài)權(quán)限控制叉存;
業(yè)務(wù)邏輯跳轉(zhuǎn)時(shí)码俩,校驗(yàn)是否已經(jīng)登錄;
甚至是代碼調(diào)試等歼捏。
ASM可以修改class字節(jié)碼文件實(shí)現(xiàn)編譯插樁
實(shí)現(xiàn)思路
1稿存、遍歷class Gradle1.5.0后我們可以自定義Transform來(lái)獲取class文件引用,但是Transform依賴(lài)Gradle Plugin因此我們要自己創(chuàng)建Gradle Plugin自定義Transform 來(lái)找到class文件
因此我們第一步需要?jiǎng)?chuàng)建一個(gè)單獨(dú)的 Gradle Plugin瞳秽,并在 Gradle Plugin 中使用自定義?Transform?找出所有的 .class 文件瓣履。
2、遍歷到目標(biāo) .class 文件 (Activity)之后练俐,通過(guò) ASM 動(dòng)態(tài)注入需要被插入的字節(jié)碼
創(chuàng)建自定義Gradle插件
1.項(xiàng)目中創(chuàng)建一個(gè)新的 module袖迎,并選擇 Android Library 類(lèi)型
2.?module 中除了 build.gradle 和 main 文件夾之外的所有內(nèi)容都刪除。然后在 main 目錄下分別創(chuàng)建 groovy 和 java 目錄腺晾,因?yàn)镚radle插件是使用groovy語(yǔ)言編寫(xiě)的燕锥,所以需要新建一個(gè)groovy目錄,用來(lái)存放插件相關(guān)的.groovy類(lèi)悯蝉。但ASM是java層面的框架归形,所以在java目錄里存放。
3鼻由、編寫(xiě)插件 這里不詳細(xì)介紹...
4.?修改module 的 build.gradle內(nèi)容
5.最后一步暇榴,創(chuàng)建 properties 文件,至此蕉世,自定義 Gradle 插件就已經(jīng)寫(xiě)完蔼紧,現(xiàn)在可以在 Android Studio 的右邊欄找到 Gradle 中點(diǎn)擊 uploadArchives,執(zhí)行 plugin 的部署任務(wù)讨彼。
自定義 Transform
混淆(proguard)歉井、分包(multi-dex)、jar 包合并(jarMerge)等都是Transform實(shí)現(xiàn)的
Transform 主要作用是檢索項(xiàng)目編譯過(guò)程中的所有文件
1哈误、創(chuàng)建*.groovy文件(具體實(shí)現(xiàn)不詳細(xì)寫(xiě)了),并繼承 Transform 類(lèi)躏嚎,完成后在plugin中注冊(cè)Transform蜜自,這樣plugin和Transform 就關(guān)聯(lián)起來(lái)了,接下來(lái)需要使用ASM將字節(jié)碼插入到目標(biāo)文件中
使用 ASM卢佣,插入字節(jié)碼到 Activity 文件
ASM有解析重荠、訪問(wèn)、寫(xiě)入相關(guān)類(lèi)虚茶,編寫(xiě)
1戈鲁、plugin 的 build.gradle 中仇参,添加對(duì) ASM 的依賴(lài)
2、在plugin module中的src/main/java目錄下創(chuàng)建包asm包婆殿,實(shí)現(xiàn)訪問(wèn)目標(biāo)類(lèi)并插入字節(jié)碼诈乒。
3、修改 自定義的 transform 中的transform 方法婆芦,并將需要插樁的字節(jié)碼插入到目標(biāo)文件中
這里只記錄實(shí)現(xiàn)步驟怕磨。。消约。