使用Android Stduio开启混淆
本篇主要介绍在Studio中lib库中jar包的混淆和phone中对apk的混淆
一.对app 主module的混淆
方法很简单,主module下的build.gradle中有buileTypes的定义如下:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
其中minifyEnabled是控制是否开启混淆,若需要在debug和release中都开启混淆,可以将其改为如下方式:
buildTypes {
debug{
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
开启混淆即可。剩余的工作就是配置proguard-rules.pro这个混淆配置文件。我们统一在下面说
二.对lib工程进行混淆打出混淆的jar包
这里我们有两种方式
(1).如一中所示,在build.gradle中将minifyEnabled配置为true即可,完成proguard-rules.pro的配置后会在对应工程目录下的build/intermediates/bundles目录中生成对应的class.jar文件(debug or default目录)最后将其copy出改名即可
(2)通过修改module目录下的build.gradle在生成未混淆的class.jar文件再次将其进行混淆
代码如下:
//下述为混淆jar包的方式
task deleteOldJar(type: Delete) {
//不混淆的jar
delete 'build/libs/unPro_passportsdk.jar'
//混淆的jar
delete 'build/libs/passportsdk.jar'
}
task exportJar(type: Copy) {
from('build/intermediates/bundles/debug/')
into('build/libs/')
include('classes.jar')
rename ('classes.jar', 'unPro_passportsdk.jar')
}
task makeJar(type: ProGuardTask, dependsOn: "build") {
// 未混淆的jar
injars 'build/libs/unPro_passportsdk.jar'
// 混淆后的jar路径
outjars 'build/libs/Pro_passportsdk.jar'
// 具体需要keep住的类
configuration'proguard-rules.pro'// 混淆配置文件
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
}
makeJar.dependsOn(deleteOldJar,exportJar,build);
执行makeJar任务即可在build/libs文件中找到混淆的Pro_passportsdk.jar和未混淆的unPro_passportsdk.jar
三.proguard-rules.pro混淆配置
开启混淆开关后主要的还是配置混淆内容,Google给了我们示例,在android-sdk/tools/proguard/proguard-android.txt中进行占时,有需要的可以去查看下官方建议配置,这里给出常用的配置:
-optimizationpasses 5 # 指定代码的压缩级别
-dontusemixedcaseclassnames # 是否使用大小写混合
-dontskipnonpubliclibraryclasses # 是否混淆第三方jar
-dontpreverify # 混淆时是否做预校验
-verbose # 混淆时是否记录日志
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 混淆时所采用的算法
-keep public class * extends android.app.Activity # 保持哪些类不被混淆
-keep public class * extends android.app.Application # 保持哪些类不被混淆
-keep public class * extends android.app.Service # 保持哪些类不被混淆
-keep public class * extends android.content.BroadcastReceiver # 保持哪些类不被混淆
-keep public class * extends android.content.ContentProvider # 保持哪些类不被混淆
-keep public class * extends android.app.backup.BackupAgentHelper # 保持哪些类不被混淆
-keep public class * extends android.preference.Preference # 保持哪些类不被混淆
-keep public class com.android.vending.licensing.ILicensingService # 保持哪些类不被混淆
-keepclasseswithmembernames class * { # 保持 native 方法不被混淆
native ;
}
-keepclasseswithmembers class * { # 保持自定义控件类不被混淆
public (android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public (android.content.Context, android.util.AttributeSet, int); # 保持自定义控件类不被混淆
}
-keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆
public void *(android.view.View);
}
-keepclassmembers enum * { # 保持枚举 enum 类不被混淆
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable { # 保持 Parcelable 不被混淆
public static final android.os.Parcelable$Creator *;
}
-keep class MyClass; # 保持自己定义的类不被混淆
四.常见错误分析及解决办法
- can't find referenced class okhttp3.Call 或者 can't find superclass or interface
报错如下:
在proguard-rules.pro中添加需要keep的 class or interface
- java.io.IOException: The output jar is empty. Did you specify the proper '-keep' options?
这里报错是需要keep入口函数。如图所示
这里keep主类如下
-keep class com.test.myTest{*;}
注意上述的函数内容全部keep.不要忘记后面的大括号,不然可以正常编译通过,但是入口函数在内部为空实现
- keep之后扔不错未引用
这里需要注意的是使用去除waring的参数 例如
-dontwarn android.widget.Toast
PS :如大家有混淆问题可在下方留言