Bootstrap

安卓编译之冰山一角——方法参数名

前言

当 library 启用 proguard 混淆打包成 aar 供第三方调用时,方法的参数名会被删除掉,这样用户就不知道参数的含义,然而作为一个库应该保留参数名。

过程

测试代码:

接下来就是打包 aar 了,这里省略流程。用 jadx 查看一下编译出来的 aar 文件,方法的参数名很显然不是我们自己写的名字,这就是被编译器抹掉了。像这种不存在参数信息的 aar 放到 Android Studio 里用会显示 p0 p1 p2 ... 

于是可以在 proguard-rules.pro 中添加:

-keepparameternames
-keepattributes MethodParameters

编译后再用 jadx 打开看一下,结果和原来的还是一样,猜测参数名应该是在混淆前抹掉的。从 apk 的编译流程可知,混淆前的流程就是 javac 编译源码,后来查阅相关资料才发现 javac 默认不保留这些调试信息,方法参数名也包括在内。


幸运的是,javac 提供了参数用于保留这些调试信息:

所以我们应该在 gradle 里给 javac 添加编译参数:

Groovy:

android{
    ...
    tasks.withType(JavaCompile) {
        options.compilerArgs += ["-g", "-parameters"]
    }
    ...
}

Kotlin:

android{
    ...
    tasks.withType<JavaCompile> {
        options.compilerArgs.addAll(listOf("-g", "-parameters"))
    }
    ...
}

再次编译:

可以看到参数被保留了。但这只是针对 java 源文件,现在的趋势都是 kotlin ,测试了一下 kotlin 编译后的参数名还是被删掉了,偶然发现 kotlinOptions ,尝试配置:

// app/build.gradle.kts

kotlinOptions {
    javaParameters = true
}

编译后 kotlin 的参数名信息也被保留了~

撒花

最后要注意的是,当开启 proguard 后,只有被 keep 的类才会保留参数名。也就是说,就算你按照上述步骤配置了保留参数,proguard-rules.pro 里不配置 keep class 的话参数名依然会被抹掉。

;