使用gradle插件修改class(onClick方法)

use gradle plug to modify class (onClick method)

我想在所有活动中使用 gradle 修改 onClick 方法,但是当我反映 onClick 方法时收到错误消息,javassist.CannotCompileException:找不到 android.view.View,这是代码,整个项目是 https://github.com/cococa/LearmProject/tree/master/Android/MixpanelTest

public class MyTransform extends Transform{


Project project

public MyTransform(Project project) {
    this.project = project
}

@Override
String getName() {
    return "MyTrans"
}

@Override
Set<QualifiedContent.ContentType> getInputTypes() {
    return TransformManager.CONTENT_CLASS
}

// 指定Transform的作用范围
@Override
Set<QualifiedContent.Scope> getScopes() {
    return TransformManager.SCOPE_FULL_PROJECT
}

@Override
boolean isIncremental() {
    return false
}

@Override
void transform(Context context, Collection<TransformInput> inputs,
               Collection<TransformInput> referencedInputs,
               TransformOutputProvider outputProvider, boolean isIncremental)
        throws IOException, TransformException, InterruptedException {
    inputs.each {TransformInput input ->
        input.directoryInputs.each {DirectoryInput directoryInput->

            // modify onClick 
            Modifyer.injectDir(directoryInput.file.absolutePath,"com/cocoa/test")

            def dest = outputProvider.getContentLocation(directoryInput.name,
                    directoryInput.contentTypes, directoryInput.scopes,
                    Format.DIRECTORY)

            FileUtils.copyDirectory(directoryInput.file, dest)
        }
        input.jarInputs.each {JarInput jarInput->

            def jarName = jarInput.name
            def md5Name = DigestUtils.md5Hex(jarInput.file.getAbsolutePath())
            if(jarName.endsWith(".jar")) {
                jarName = jarName.substring(0,jarName.length()-4)
            }

            def dest = outputProvider.getContentLocation(jarName+md5Name,
                    jarInput.contentTypes, jarInput.scopes, Format.JAR)
            FileUtils.copyFile(jarInput.file, dest)
        }
    }
}

}

public class Modifyer {


private static ClassPool pool = ClassPool.getDefault()

public static void injectDir(String path, String packageName) {
    println "injectDir---------"
    pool.appendClassPath(path)
    File dir = new File(path)
    if (dir.isDirectory()) {
        dir.eachFileRecurse { File file ->
            String filePath = file.absolutePath

            if (filePath.endsWith(".class")
                    && !filePath.contains('R$')
                    && !filePath.contains('R.class')
                    && !filePath.contains("BuildConfig.class")) {

                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('/', '.')
                    //get the class <like MainActivity.class>
                    CtClass c = pool.getCtClass(className)

                    if (c.isFrozen()) {
                        c.defrost()
                    }

                    try {
                        println "injectDir---------" + c.getName()

                        CtMethod[] methods = c.getDeclaredMethods();
                        for (CtMethod m : methods) {
                            println "injectDir---------" + m.getName()
                            if (m.getName().equals("onClick")) {  //at this ,always get Exception  javassist.CannotCompileException: cannot find android.view.View


                                m.insertBefore("com.cocoa.mixpaneltest.Logger.log();");
                                println "injectDir---------" + m.getName()
                            }
                        }

                    } catch (Exception e) {
                        println "injectDir---------" + e.toString()
                    }
                    c.writeFile(path)
                    c.detach()
                }
            }
        }
    }
}

}

public class PluginImpl implements Plugin<Project> {
void apply(Project project) {
        def android = project.extensions.findByType(AppExtension)
        android.registerTransform(new MyTransform(project))

}

}

您需要将 android.jar 追加到 class 池,以便 javassist 可以编译。 这是一个已知问题,请检查 https://github.com/realm/realm-java/issues/2703

project.android.bootClasspath.each {
        String path = it.absolutePath
        classPool.appendClassPath(path)
}