代碼混淆部分
gradle的配置
minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
proguard-rules.pro混淆配置
###-----------基本配置-不能被混淆的------------ -keep public class * extends android.app.Activity -keep public class * extends android.app.Fragment -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 #support.v4/v7包不混淆 -keep class android.support.** { *; } -keep class android.support.v4.** { *; } -keep public class * extends android.support.v4.** -keep interface android.support.v4.app.** { *; } -keep class android.support.v7.** { *; } -keep public class * extends android.support.v7.** -keep interface android.support.v7.app.** { *; } -dontwarn android.support.** # 忽略警告 #保持注解繼承類不混淆 -keep class * extends java.lang.annotation.Annotation {*;} #保持Serializable實現類不被混淆 -keepnames class * implements java.io.Serializable #保持Serializable不被混淆並且enum 類也不被混淆 -keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve(); } #保持枚舉enum類不被混淆 -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } #自定義組件不被混淆 -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*(...); } #不混淆資源類 -keepclassmembers class **.R$* { public static <fields>; } ###-----------第三方jar包library混淆配置------------ #ormlite混淆配置 #-libraryjars libs/ormlite-android-5.0.jar #-libraryjars libs/ormlite-core-5.0.jar -dontwarn com.j256.ormlite.** -keep class com.j256.ormlite.** { *;} -keep class com.envy15.cherry.base.orm.** { *;} #json-lib混淆配置 #-libraryjars libs/json-lib-2.4-jdk15.jar -dontwarn net.sf.json.** -keep class net.sf.json.** { *;} #json-lib關聯包 #-libraryjars libs/commons-beanutils-1.8.3.jar -dontwarn org.apache.commons.** -keep class org.apache.commons.** { *;} #universalimageloader圖片加載框架不混淆 -keep class com.nostra13.universalimageloader.** { *; } -dontwarn com.nostra13.universalimageloader.** #Gson相關的不混淆配置 -keepattributes Signature -keepattributes *Annotation* -keep class com.google.gson.** { *; } -dontwarn com.google.gson.** -keep class com.envy15.cherry.fragment.crossover.model.** { *; } -dontwarn com.envy15.cherry.fragment.crossover.model.** -keep class com.envy15.cherry.fragment.discover.model.** { *; } -dontwarn com.envy15.cherry.fragment.discover.model.** -keep class com.envy15.cherry.fragment.local.model.** { *; } -dontwarn com.envy15.cherry.fragment.local.model.** -keep class com.envy15.cherry.fragment.setting.model.** { *; } -dontwarn com.envy15.cherry.fragment.setting.model.** #prt-lib下拉刷新框架不混淆 -keep class in.srain.cube.views.ptr.** { *; } -dontwarn in.srain.cube.views.ptr.** #PullToRefreshLibrary下拉刷新框架不混淆 -keep class com.handmark.pulltorefresh.library.** { *; } -dontwarn com.handmark.pulltorefresh.library.** #參考: # http://blog.csdn.net/zuiwuyuan/article/details/48552701 # http://blog.csdn.net/fengyuzhengfan/article/details/43876197 # http://blog.isming.me/2014/05/31/use-proguard/ # http://hanhailong.com/2015/12/28/Android%E8%BF%9B%E9%98%B6%E4%B9%8BProGuard%E4%BB%A3%E7%A0%81%E6%B7%B7%E6%B7%86/ # 關於混淆的思考: # https://www.zhihu.com/question/37446729 # 擴展:資源文件混淆 # http://blog.csdn.net/Fancy_xty/article/details/51202866 #代碼混淆規則 # 指定代碼的壓縮級別 #-optimizationpasses 5 # 是否使用大小寫混合 #-dontusemixedcaseclassnames # 是否混淆第三方jar #-dontskipnonpubliclibraryclasses # 混淆時是否做預校驗 #-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 <methods>; #} # #-keepclasseswithmembers class * { # 保持自定義控件類不被混淆 # public <init>(android.content.Context, android.util.AttributeSet); #} # #-keepclasseswithmembers class * { # public <init>(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; # 保持自己定義的類不被混淆
打包發布部分
S1.使用默認方式打包簽名APK
AndroidStudio選擇Build => Generate Signed APK
總體步驟流程如下:
詳細操作步驟:
S2. 多渠道打包APK
屬性配置 |
productFlavors |
productFlavors { aVer { resValue("string","strKey","myKey") applicationId "com.simple.pkg.debug" } bVer { applicationId "com.simple.pkg.beta" } cVer { applicationId "com.simple.pkg.res" } } |
signingConfigs |
signingConfigs { release { storeFile file('E:/XXX/app.jks') // 簽名證書文件 storePassword 'you password' // 證書密碼 keyAlias 'test' keyPassword 'you password ' } } |
buildTypes |
buildTypes { mbeta { signingConfig android.signingConfigs.release minifyEnabled false } } |
S3.gradle打包自動化-定制apk文件名
gradle屬性及變量定義的幾種方式
變量定義 |
方式1(for gradle) |
工程目錄下gradle.properties定義屬性:appName = MyAppName App目錄下build.gradle讀取自定義屬性:project.appName |
方式2(for java) |
App目錄下build.gradle定義屬性: productFlavors { aVer { // gradle定義全局變量方式2-代碼使用 buildConfigField "int", "varInt", "0" buildConfigField "String", "varString", '"abc"' } } Java代碼讀取屬性:BuildConfig.varInt;BuildConfig.varString; |
方式3(for java) |
App目錄下build.gradle定義屬性: productFlavors { aVer { resValue("string","strKey","myKey") } } ava代碼讀取屬性:context.getString(R.string.strKey); |
方式4 |
App目錄下build.gradle定義屬性: def flavorName = "undefine" def indexFlavor(String str) { return str.substring(0,str.length()) } |
方式5 |
App目錄AndroidManifest.xml定義變量 <meta-data android:name="env_key0" android:value="${env_val0}" /> build.gradle修改env_val0 buildTypes { debug { minifyEnabled false manifestPlaceholders = [env_val0: "VAL0", env_val1: "VAL1"] } } Java代碼中獲取meta屬性定義 public static String getMetaValue(Context context,String key){ ApplicationInfo applicationInfo = null; try { applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } if (applicationInfo == null){ return ""; } return applicationInfo.metaData.getString(key); } |
Ref:
android studio gradle 多版本多apk打包(打包系列教程之五)
定制apk文件名
變量定義 |
自定義生成APK文件名 |
applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile // appName + version + createTime + svnVersion + flavor + buildType def fileName = "fileName.apk" output.outputFile = new File(outputFile.parent, fileName) } } |
獲取相關屬性 |
AppName:自定義方式或getName() Version:版本, defaultConfig.versionName CreateTime:創建時間,new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC")) SvnVersion :SVN提交版本號 BuildType:debug/beta/release版本 def fileName = "${project.appName}_v${defaultConfig.versionName}_${releaseTime()}_" + "s${getSvnRevision()}_${indexFlavor(productFlavors.name)}_${getName()}.apk" |
|
|
Ref:
Android Gradle實用技巧——APK文件名中加上SVN版本號,日期等
參考問題:
buildTypes中加上signingConfig sigingConfigs.release運行就報錯
build.gradle多渠道打包完整示例
// app/build.gradle文件 import org.tmatesoft.svn.core.wc.* // for svn version apply plugin: 'com.android.application' def releaseTime() { return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC")) } def indexFlavor(String str) { return str.substring(0,str.length()) } def getSvnRevision() { // for svn ISVNOptions options = SVNWCUtil.createDefaultOptions(true); SVNClientManager clientManager = SVNClientManager.newInstance(options); SVNStatusClient statusClient = clientManager.getStatusClient(); SVNStatus status = statusClient.doStatus(projectDir, false); SVNRevision revision = status.getCommittedRevision(); return revision.getNumber(); } android { signingConfigs { } compileSdkVersion 25 buildToolsVersion "25.0.2" defaultConfig { applicationId "com.simple.res" minSdkVersion 15 targetSdkVersion 21 versionCode 1 versionName "1.0" multiDexEnabled true // dex突破65535的限制 } productFlavors { aVer { // gradle定義全局變量方式2-代碼使用 buildConfigField "int", "varInt", "0" buildConfigField "String", "varString", '"abc"' // resValue("string","strKey","myKey") applicationId "com.simple.res.debug" } bVer { applicationId "com.simple.res.beta" } } signingConfigs { release { storeFile file('E:/XXX/App.jks') storePassword 'you password' keyAlias 'TEST' keyPassword 'you password' } } buildTypes { debug { minifyEnabled false } mbeta { signingConfig android.signingConfigs.release minifyEnabled false } release { signingConfig android.signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' minifyEnabled true shrinkResources true // 指定APK文件名 applicationVariants.all { variant -> variant.outputs.each { output -> def outputFile = output.outputFile // appName + version + createTime + svnVersion + flavor + buildType def fileName = "${project.appName}_v${defaultConfig.versionName}_${releaseTime()}_" + "s${getSvnRevision()}_${indexFlavor(productFlavors.name)}_${getName()}.apk" output.outputFile = new File(outputFile.parent, fileName) } } } } } // project/build.gradle文件 // 添加classpath group: 'org.tmatesoft.svnkit', name: 'svnkit', version: '1.8.11'支持獲取// SVN提交版本號 buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.3' classpath group: 'org.tmatesoft.svnkit', name: 'svnkit', version: '1.8.11' } // project/build.gradle文件 appName = NewApp
* 崩潰日志記錄 * 參考: * http://blog.csdn.net/u012333411/artile/details/49019415 * http://blog.csdn.net/wangyuexing_blog/article/details/39009069