整理下最近工作中混淆代码时遇到的问题,gradle混淆脚本Android Studio 使用 Gradle 打包 Jar感谢这位博主。
打jar包
task makeJar(dependsOn: ['compileReleaseJavaWithJavac'], type: Jar) {
appendix = "demo"
baseName = "androidJar"
version = "1.0.0"
classifier = "release"
//后缀名
extension = "jar"
//最终的 Jar 包名,如果没设置,默认为 [baseName]-[appendix]-[version]-[classifier].[extension]
archiveName = "DydGameSDKLib.jar"
//需打包的资源所在的路径集
def srcClassDir = [project.buildDir.absolutePath + "/intermediates/classes/release"];
//初始化资源路径集
from srcClassDir
//去除路径集下部分的资源
exclude "com/yourPackegeName/game/BuildConfig.class"
exclude "**/R.class"
exclude "**/R\$*.class"
//只导入资源路径集下的部分资源
include "com/yourPackegeName/**/*.class"
}
导出混淆包
task proguardJar(dependsOn: ['makeJar'], type: ProGuardTask) {
//Android 默认的 proguard 文件
configuration android.getDefaultProguardFile('proguard-android.txt')
//manifest 注册的组件对应的 proguard 文件
configuration 'proguard-rules.pro'
String inJar = makeJar.archivePath.getAbsolutePath()
//输入 jar
injars inJar
//输出 jar
outjars inJar.substring(0, inJar.lastIndexOf(File.separator)) + "/proguard-${makeJar.archiveName}"
//设置不删除未引用的资源(类,方法等)
dontshrink
Plugin plugin = getPlugins().hasPlugin(AppPlugin) ?
getPlugins().findPlugin(AppPlugin) :
getPlugins().findPlugin(LibraryPlugin)
if (plugin != null) {
List<String> runtimeJarList
if (plugin.getMetaClass().getMetaMethod("getRuntimeJarList")) {
runtimeJarList = plugin.getRuntimeJarList()
} else if (android.getMetaClass().getMetaMethod("getBootClasspath")) {
runtimeJarList = android.getBootClasspath()
} else {
runtimeJarList = plugin.getBootClasspath()
}
for (String runtimeJar : runtimeJarList) {
//给 proguard 添加 runtime
libraryjars(runtimeJar)
}
}
}
混淆文件proguard-android.txt
-keep class com.yourPackegeName.aidl.** { *;}
-keep class com.yourPackegeName.game.activity.** { *;}
-keepattributes Exceptions,InnerClasses
-keep class com.yourPackegeName.game.api.* { *;}
-keepclassmembers class com.yourPackegeName.game.api.** { *;}
-keep class com.yourPackegeName.game.callback.** { *;}
-keep class com.yourPackegeName.game.entity.** { *;}
-keepclassmembers class com.yourPackegeName.game.dialog.AvatarImageListener{*;}
-keepclassmembers class com.yourPackegeName.game.network.DydErrorListener{*;}
-keepclassmembers class com.yourPackegeName.game.network.SuccessListener{*;}
-keepclassmembers class com.yourPackegeName.game.network.model.*{*;}
-keepclassmembers class com.yourPackegeName.game.network.util.DydOkHttpNetwork{ *;}
-keepclassmembers class com.yourPackegeName.game.network.util.DydStringRequest{ *;}
-keepclassmembers class com.yourPackegeName.game.network.util.OkHttpStack{ *;}
-keepclassmembers class com.yourPackegeName.game.network.util.DydImageCatch{ *;}
-keepattributes Signature
-keep public class * extends android.view.View {
public (android.content.Context);
public (android.content.Context, android.util.AttributeSet);
public (android.content.Context, android.util.AttributeSet, int);
public void set*(***);
*** get* ();
}
-dontwarn com.android.volley.**
-dontwarn com.alibaba.fastjson.**
-dontwarn android.support.v4.**
-dontwarn org.apache.**
-dontwarn com.pingplusplus.**
-dontwarn okio.**
-dontwarn com.squareup.**
-dontwarn android.webkit.**
-dontwarn com.yourPackegeName.**
-dontwarn android.**
-dontwarn com.ta.utdid2.**
参数解释
-keep {Modifier} {class_specification} 保护指定的类文件和类的成员
-keepclassmembers {modifier} {class_specification}保护指定类的成员,如果此类受到保护他们会保护的更好
-dontwarn 忽略警告
-keep public class * extends android.view.View {
public (android.content.Context);
public (android.content.Context, android.util.AttributeSet);
public (android.content.Context, android.util.AttributeSet, int);
public void set*(***);
*** get* ();
}
忽略自定义view
-keepattributes Signature忽略泛型
-keepattributes Exceptions,InnerClasses忽略异常和内部类
问题记录
1.java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
一般是混淆的时候泛型没有被保留导致class cast时出错
解决:-keepattributes Signature
2.内部类找不到
解决:
-keepattributes Exceptions,InnerClasses
也可以A$*表示保留所有内部类
-keep class com.xxx.A
-keep class com.xxx.A$*
只保留某一个内部类
-keep class com.xxx.A
-keep class com.xxx.A$B
3.混淆过程中引用的包抛出warning导致混淆失败
解决:-dontwarn com.alibaba.fastjson.** 告诉编译器不要提示这个包的警告
4.java.lang.AbstractMethodError: abstract method not implemented,这种错误是因为使用匿名内部类时,类的实现方法被混淆,导致找不到具体的实现方法例如有个类或者接口
A{ a()}
A a = new A(){
a(){
.......
}
}
解决办法:将匿名内部类提出到内部类或者一个新的类再混淆,暂时没找到其他办法
5.如果有类继承或者实现其他的类/接口,使用-keepclassmembers class 保护类的成员以免重写的方法被混淆不能正确的调用