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