赞
踩
对于proguardFiles这部分有两段,前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,免去了我们很多事,这个文件的目录在 /tools/proguard/proguard-android.txt , 后一部分是我们项目里的自定义的混淆文件,目录就在 app/proguard-rules.txt
下面是gradle配置:(注意,minifyEnabled置为false的情况下,zipAlignEnabled 和 shrinkResources 也要置为false,否则会编译报错)
buildTypes { release { // 是否进行混淆 minifyEnabled true //不显示log buildConfigField "boolean", "LOG_DEBUG", "false" //Zipalign优化 zipAlignEnabled true // 移除无用的resource文件 shrinkResources true //签名文件 signingConfig signingConfigs.release //在gradle中引用的签名文件 //对应的混淆文件 proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug{ debuggable true signingConfig signingConfigs.debug } }
1.AndroidMainfest中的类不混淆,四大组件和Application的子类和Framework层下所有的类默认不会进行混淆。
2.反射用到的类不混淆
3.JNI方法不混淆
4.Parcelable的子类和Creator的静态成员变量不能混淆,否则会产生BadParcelableException异常。
5.有用到webView的JS调用也需要保证写的接口方法不混淆。
6.使用GSON、fastjson等框架时,所写的JSON对象类(即bean包下的所有类)不混淆,否则无法将JSON解析成对应的对象。
7.使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则。
8.R类里及其所有内部static类中的所有static变量字段不混淆。
1.-libraryjars class_path 应用的依赖包,如android-support-v4
2.-keep [,modifier,...] class_specification 不混淆某些类
3.-keepclassmembers [,modifier,...] class_specification不混淆类的成员
4.-keepclasseswithmembers [,modifier,...]class_specification 不混淆类及其成员
5.-keepnames class_specification 不混淆类及其成员名
6.-keepclassmembernames class_specification 不混淆类的成员名
7.-keepclasseswithmembernames class_specification 不混淆类及其成员名
8.-assumenosideeffects class_specification 假设调用不产生任何影响,在proguard代码优化时会将该调用remove掉。如system.out.println和Log.v等等
9.-dontwarn [class_filter] 不提示warnning
1. mapping.txt
-printmapping mapping.txt
表示混淆前后代码的对照表,这个文件非常重要。如果你的代码混淆后会产生bug的话,log提示中是混淆后的代码,希望定位到源代码的话就可以根据mapping.txt反推。
每次发布都要保留它方便该版本出现问题时调出日志进行排查,它可以根据版本号或是发布时间命名来保存或是放进代码版本控制中。
2. dump.txt
-dump class_files.txt
描述apk内所有class文件的内部结构。
3. seeds.txt
-printseeds seeds.txt
列出了没有被混淆的类和成员。
4. usage.txt
-printusage unused.txt
列出了源代码中被删除在apk中不存在的代码。
#指定代码的压缩(proguard对代码进行迭代优化的次数0-7)等级Android中一般设置为5 -optimizationpasses 5 #包名不使用大小写混合 -dontusemixedcaseclassnames # 不混淆第三方引用的库 -dontskipnonpubliclibraryclasses # 不做预校验 -dontpreverify # 忽略警告 -ignorewarning #apk 包内所有 class 的内部结构 -dump class_files.txt #未混淆的类和成员 -printseeds seeds.txt #列出从 apk 中删除的代码 -printusage unused.txt #混淆前后的映射 -printmapping mapping.txt # 保持Activity类及其子类不被混淆 -keep public class * extends android.app.Activity # 保持Application类及其不被混淆 -keep public class * extends android.app.Application # 保持Service类及其子类不被混淆 -keep public class * extends android.app.Service # 保持BroadcastReceiver类及其不被混淆 -keep public class * extends android.content.BroadcastReceiver # 保持ContentProvider类及其子类不被混淆 -keep public class * extends android.content.ContentProvider # 保持BackupAgentHelper类及其子类不被混淆 -keep public class * extends android.app.backup.BackupAgentHelper # 保持Preference类及其子类不被混淆 -keep public class * extends android.preference.Preference # 保持Fragment类及其子类不被混淆 -keep public class * extends android.app.Fragment #保持引用v4包下Fragment及其子类不被混淆 -keep public class * extends android.support.v4.app.Fragment #保持 Serializable类及其实现类不被混淆 -keepnames class * implements java.io.Serializable # 如果引用了v4或者v7包 -dontwarn android.support.** # 保持 native 方法不被混淆 -keepclasseswithmembernames class * { native <methods>; } #保护注解 -keepattributes *Annotation* -keep class * extends java.lang.annotation.Annotation {*;} # 不混淆内部类 -keepattributes InnerClasses #不混淆资源类即R文件 -keepclassmembers class **.R$* { public static <fields>; } #避免混淆泛型 如果混淆报错建议关掉 -keepattributes Signature # 保持枚举 enum 类不被混淆 -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } # 保持自定义控件类不被混淆 -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet); } # 保持自定义控件类不被混淆 -keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); } # 保持Activity中参数类型为View的所有方法 -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } #保持所有bean类(即bean包下所有类)都不被混淆 -keep class android.launcher.bean.**{ *; } #所有View的子类及其子类的get、set方法都不进行混淆 -keep public class * extends android.view.View { public <init>(android.content.Context); public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int); public void set*(...); } # 保持包含org.json.JSONObject参数的构造方法的类 -keepclassmembers class * { public <init> (org.json.JSONObject); } # 有用到WEBView的JS调用接口不被混淆 -keepclassmembers class fqcn.of.javascript.interface.for.webview { public *; } #移除log 测试了下没有用还是建议自己定义一个开关控制是否输出日志 -assumenosideeffects class android.util.Log { public static boolean isLoggable(java.lang.String, int); public static int v(...); public static int i(...); public static int w(...); public static int d(...); public static int e(...); } #友盟推送的混淆配置 -dontwarn com.taobao.** -dontwarn anet.channel.** -dontwarn anetwork.channel.** -dontwarn org.android.** -dontwarn org.apache.thrift.** -dontwarn com.xiaomi.** -dontwarn com.huawei.** -keep class com.taobao.** {*;} -keep class org.android.** {*;} -keep class anetwork.channel.**{*;} -keep class anet.channel.** {*;} -keep class com.umeng.** {*;} -keep class com.xiaomi.** {*;} -keep class com.huawei.** {*;} -keep class org.apache.thrift.** {*;} -keep public class **.R$*{ public static final int *; } #友盟统计的混淆配置1、R文件的混淆保护2、枚举混淆3、JSON混淆 #因为上面都有配置故不做重复配置 #展示互动混淆配置 -dontwarn com.gensee.** -keep class com.gensee.**{*;} #universal-image-loader包 -keep class com.nostra13.universalimageloader.** { *; } #CC视频 jar包 -dontwarn com.bokecc.sdk.mobile.** -keep public class com.bokecc.sdk.mobile.**{*;} -keep public interface com.bokecc.sdk.mobile.**{*;} #混淆保护自己项目的部分代码以及引用的第三方jar包library #-libraryjars libs/universal-image-loader-1.9.5.jar #-libraryjars libs/opensdk.jar #-libraryjars libs/butelCommConnect.jar #自定义的下拉刷新GridView -keep class com.chanven.lib.cptr.**{*;} #Volley -dontwarn com.android.volley.jar.** -keep class com.android.volley.**{*;}
我们打开要打包的module下的build配置文件这里会有两个方法,一个普通方法,一个快捷方法。
1. 普通方法:
roductFlavors {
wandoujia {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
}
baidu {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]
}
c360 {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "c360"]
}
uc {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "uc"]
}
}
2:快捷方法
productFlavors {
wandoujia {}
baidu {}
c360 {}
...
roductFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}
首先要配置好gradle的环境变量方便我们在Terminal的方式(cmd应该也可以,没试过),运行打包命令,如果不知道的话,我先贴出配置方法吧(其实跟java配置环境变量一样一样的)
先找到gralde的根目录,在系统变量里添加两个环境变量:
变量名为:GRADLE_HOME,变量值就为gradle的根目录;
所以变量值为:C:\Users\ping\.gradle\wrapper\dists\gradle-2.1-all\27drb4udbjf4k88eh2ffdc0n55\gradle-2.1
还有一个在系统变量里PATH里面添加gradle的bin目录
我的就是C:\Users\ping\.gradle\wrapper\dists\gradle-2.1-all\27drb4udbjf4k88eh2ffdc0n55\gradle-2.1\bin
这里配置完成了,接着在Terminal中敲下 gradle assembleRelease 就可以一次性生成所有的渠道包了。所有生成的apk在项目的 build\outputs\apk 下。
在打包完成后需要保存基线版本,关于基线版本需要保存的文件说明:
1.如果项目集成了tinker那么需要保留app/build/bakApk文件夹,留作热部署时的基线参考。
2.项目如果集成了友盟统计那么需要保留app/build/outputs文件夹,主要保留mapping文件,因为mapping文件存储了代码混淆对应。通过友盟统计上传对应版本的mapping文件能准确定位发生bug的位置。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。