Gradle custom plugin +Transform+ Javassist makes something like JakeWharton’s Hugo library
Special note: This article has reference to code later and copied the (http://blog.csdn.net/eclipsexys/article/details/50973205) (https://github.com/HalfStackDeveloper/Savior), And slap the great spirit of the library (https://github.com/JeasonWong/CostTime), very thanks to slap a great god hold I change the code, useful to the code of the classmate, contact me, have abuse will be deleted)
Source code download address :(https://github.com/zjw-swun/AppMethodTime) feel helpful can give a star
Transform is the API of the Android Gradle plugin that participates in class packaging, and Javassist is the library that generates or modiates class bytecodes. With these two features, we can do something like JakeWharton’s Hugo library.
1. Build a new BuildSrc Module (lib Module, BuildSrc name fixed) and start with SRC (including SRC).
2. The name can be different than the first method, but you need to bring the META folder.
MavenDeployer uploadArchives {repositories {mavenDeployer {pom.groupid ='com.branch.plugin'
pom.artifactId = 'dellog'
pom.version = '1.0.0'// Publish the file to the following directory: repository(url: uri('.. /repo'))}}}Copy the code
And then I’m going to run uploadArchives and I’m not going to go into details but I’ll look at the code
The core is MyTransform class, and MyInject class MyInject class inside the code as follows
package com.zjw.plugin import javassist.* public class MyInject { private static ClassPool pool = ClassPool.getDefault() // Note that you need to replace your anroid.jar path static String androidJar ="D:\\Application\\Android\\sdkUpDate\\platforms\\android-24\\android.jar"
static String myPackageName = "com.zjw.appmethodtime";
static String myCostTimeAnnotation = "@com.zjw.appmethodtime.CostTime";
static String CostTime = "CostTime"; public static void injectDir(String path, String packageName, Boolean enabeCostTime) {pool.appendclasspath (path) // The following is your android.jar path in Windows println("enabeCostTime is " + enabeCostTime)
File dir = new File(path)
if(dir.isdirectory ()) {dir.eachFilerecurse {File File -> String filePath = file.absolutePath Class files and annotation files are not automatically generated by the systemif (filePath.endsWith(".class")
&& !filePath.contains('R$')
&& !filePath.contains('R.class')
&& !filePath.contains("BuildConfig.class")
&& !filePath.contains("CostTime"Int index = filePath. IndexOf (packageName); boolean isMyPackage = index ! = 1;if (isMyPackage) {
int end = filePath.length() - 6 // .class = 6
String className = filePath.substring(index, end).replace('\ \'.'. ').replace('/'.'. 'CtClass c = pool.getctClass (className) CtClass c = pool.getctClass (className)if(c.isfrozen ()) {c.frost ()} pool.importPackage(myPackageName) // Add the timer variable CtField startTime = new to the class CtField(CtClass.longType,"sStart", c); startTime.setModifiers(Modifier.STATIC); c.addField(startTime); CtField endTime = new CtField(ctclass.longType,"sEnd", c); endTime.setModifiers(Modifier.STATIC); c.addField(endTime); CtMethod[] methods = c.getdeclaredMethods ();for (CtMethod method : methods) {
println("method ====" + method.longName)
if(enabeCostTime && method.getAvailableAnnotations() ! = null && method.getAvailableAnnotations().length >= 1 &&"${method.getAvailableAnnotations()[0]}".contains(CostTime)
) {
insertCostTimeCode(method)
} else if(! enabeCostTime) { insertCostTimeCode(method) } }//ENDfor (CtMethod method : methods)
c.writeFile(path)
c.detach()
}//END if(isMyPackage)}}}} private static void insertCostTimeCode(CtMethod method) {// Insert into the first StringBuilder startInjectStr = new StringBuilder(); startInjectStr.append("sStart = System.nanoTime();");
print(The first sentence of the method is inserted: + startInjectStr.toString() + "Statement \ n") method.insertbefore (startInjectstr.toString ()) endInjectStr.append("sEnd = System.nanoTime(); \n");
endInjectStr.append("android.util.Log.e(\"AppMethodTime\",");
endInjectStr.append("\" " + method.longName + "\" ");
endInjectStr.append("+(send-sstart)/1000000+\" (ms)\");");
print(The last sentence of the method is inserted: + endInjectStr.toString() + "Statement \ n")
method.insertAfter(endInjectStr.toString(), true)}}Copy the code
#3. Plug-in custom configuration fields
pluginsrc{
message = 'hello gradle plugin'
cost = true
}
Copy the code
In MyTransform class
MyInject.injectDir(directoryInput.file.absolutePath,
"com" + File.separator + "zjw" + File.separator + "appmethodtime",
project.pluginsrc.cost)
Copy the code
For use. If you want to read it in a task you create in a custom plugin before your app is compiled to generate an APK
pluginsrc{
message = 'hello gradle plugin'
cost = true
}
Copy the code
If cost, you must add preBuild. DependsOn appPlugin
Not to mention the basic knowledge of custom plugins should be here renderings
return is null