??最近在學習字節(jié)碼插樁技術(shù),利用字節(jié)碼插樁技術(shù),我們可以在編譯時期對字節(jié)碼進行修改,達到完成一些特殊需求,比如埋點(可以聲明一個BaseActivity,在onCreate和onDestory中進行埋點);統(tǒng)計函數(shù)執(zhí)行時間;熱修復,ButterKnief、Dagger等也用到了字節(jié)碼插樁技術(shù)。
??在Android中要使用字節(jié)碼插樁技術(shù)需要完成三步:
- 自定義Gradle插件 :自定義插件,重寫apply方法,注冊自定義Transform
- Transform Api使用:自定義Ttransform,在transform方法中實現(xiàn)處理邏輯
-
Asm的使用: 在transform中使用Asm插入字節(jié)碼
??本文是實現(xiàn)第一步,自定義Gradle。
??實現(xiàn)自定義Gradle插件主要有三種方式:
1.在build.gradle中定義,直接在module的build.gradle中實現(xiàn),缺點:只能在本項目中使用,不好復用。
2.buildSrc中使用。這種方式需要在項目中新建一個model命名為buildSrc,這個目錄就用來存放自定義插件,缺點:只能在本項目中使用,不好復用。
3.獨立Module中使用。這種方式就是完全獨立開發(fā)一個Module,并且可以上傳至maven庫,可以隨便用。
由于三種方式實現(xiàn)都差不多,前兩種局限性比較大,所以本文只對第三種進行記錄。
1、新建Android Module選擇Android Library類型即可
??除去src/main和build.gradle其余文件都刪除,并清除build.gradle內(nèi)容,將以下內(nèi)容填入build.gradle,并同步gradle
apply plugin: 'groovy'
dependencies {
//gradle sdk
implementation gradleApi()
//groovy sdk
implementation localGroovy()
}
2、新建groovy文件,實現(xiàn)插件邏輯
??在src/main目錄下新建groovy目錄,在groovy目錄下新建com.example.clean目錄(名字自取即可),在該目錄下新建CleanPlugin.groovy文件,文件有一個綠色的G標記,表示系統(tǒng)識別為groovy文件,可以導入gradle api。如果沒有出現(xiàn)綠色標志,可以將文件名改為小寫試試。

??這個cleanplugin.groovy就是我們要實現(xiàn)插件的主要邏輯,我們需要聲明一個類來實現(xiàn)Plugin<Project>接口,在apply中實現(xiàn)主要邏輯。
package com.example.clean
import org.gradle.api.Plugin
import org.gradle.api.Project;
class cleanplugin implements Plugin<Project> {
@Override
void apply(Project project) {
println("clean plugin")
}
}
??注意記得導入包目錄,否則會導致找不到插件實現(xiàn)類
3、聲明插件
??在src/main目錄下新建resource目錄,接著新建META-INF目錄,繼續(xù)新建gradle-plugins目錄,再新建com.example.firstplugin.properties文件(名字自取),注意文件名即為到時候其他項目中引用的插件名,在該文件中寫入如下內(nèi)容
//插件實現(xiàn)類
implementation-class=com.example.clean.cleanplugin
4、將插件上傳至maven庫
??在插件的build.gradle文件中添加插件groupid、version等參數(shù)和上傳maven地址
apply plugin: 'maven-publish'
publishing {
publications {
mavenJava(MavenPublication) {
//其他項目使用插件時的方式:classpath 'com.example.clean:firstplug:1.0.0'
//三個參數(shù)
groupId 'com.example.clean'
artifactId 'firstplug'
version '1.0.0'
from components.java
}
}
}
publishing {
repositories {
maven {
// maven地址,可以是本地地址也可以是遠程地址
url uri('C:/Android/repos')
}
}
}
最終build.gradle文件內(nèi)容如下:
apply plugin: 'groovy'
apply plugin: 'maven-publish'
dependencies {
//gradle sdk
implementation gradleApi()
//groovy sdk
implementation localGroovy()
}
publishing {
publications {
mavenJava(MavenPublication) {
//其他項目使用插件時的方式:classpath 'com.example.clean:firstplug:1.0.0'
//三個參數(shù)
groupId 'com.example.clean'
artifactId 'firstplug'
version '1.0.0'
from components.java
}
}
}
publishing {
repositories {
maven {
// maven地址,可以是本地地址也可以是遠程地址
url uri('C:/Android/repos')
}
}
}
??同步gradle,在右側(cè)的gradle目錄中,找到clean下的publish任務,并運行publish,將插件上傳至maven庫。

??運行成功后,在本地的repos目錄下可以找到上傳的插件

5、引用插件
??在項目的根build.gradle文件中,添加插件引用和maven庫地址,最終build.gradle文件內(nèi)容如下:
buildscript {
repositories {
google()
jcenter()
maven {//local maven repo path
url uri('C:/Android/repos')
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.1'
classpath 'com.example.clean:firstplug:1.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
同步gradle,在app module的build.gradle文件中添加插件,如下:
//原文件的android插件
apply plugin: 'com.android.application'
//添加自定義插件,插件名即為com.example.firstplugin.properties文件名
apply plugin: 'com.example.firstplugin'
自定義插件名即為com.example.firstplugin.properties文件名,同步build.gradle,運行app下的bulid任務

出現(xiàn)"clean plugin",即自定義插件中apply方法中輸出的日志,表示插件運行成功。