首先說說混淆
我們現(xiàn)在一般都用的as,很方便,直接在build.gradle里邊設(shè)置即可
- //混淆開關(guān)
minifyEnabled false
-//Zipalign優(yōu)化
zipAlignEnabled true
- // 移除無用的resource文件
shrinkResources true
- // proguardFiles這部分有兩段批狐,前一部分代表系統(tǒng)默認(rèn)的android程序的混淆文件,該文件已經(jīng)包含了基本的混淆聲明前塔,免去了我們很多事嚣艇,這個(gè)文件的目錄在 /tools/proguard/proguard-android.txt , 后一部分是我們項(xiàng)目里的自定義的混淆文件,目錄就在 app/proguard-rules.txt
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
除了系統(tǒng)默認(rèn)的混淆文件我們不用管,我們只要注意我們的自定義混淆文件即可,在as中就是 "proguard-rules.pro" 文件
先簡單說一下混淆的一些常用語法:
-libraryjars class_path 應(yīng)用的依賴包华弓,如android-support-v4
-keep [,modifier,...] class_specification 不混淆某些類
-keepclassmembers [,modifier,...] class_specification 不混淆類的成員
-keepclasseswithmembers [,modifier,...] class_specification 不混淆類及其成員
-keepnames class_specification 不混淆類及其成員名
-keepclassmembernames class_specification 不混淆類的成員名
-keepclasseswithmembernames class_specification 不混淆類及其成員名
-assumenosideeffects class_specification 假設(shè)調(diào)用不產(chǎn)生任何影響食零,在proguard代碼優(yōu)化時(shí)會將該調(diào)用remove掉。如system.out.println和Log.v等等
-dontwarn [class_filter] 不提示warnning
再說一下Android 混淆原則:
反射用到的類不混淆
JNI方法不混淆
AndroidMainfest中的類不混淆寂屏,四大組件和Application的子類和Framework層下所有的類默認(rèn)不會進(jìn)行混淆
Parcelable的子類和Creator靜態(tài)成員變量不混淆贰谣,否則會產(chǎn)生android.os.BadParcelableException異常
使用GSON、fastjson等框架時(shí)迁霎,所寫的JSON對象類不混淆吱抚,否則無法將JSON解析成對應(yīng)的對象
使用第三方開源庫或者引用其他第三方的SDK包時(shí),需要在混淆文件中加入對應(yīng)的混淆規(guī)則
有用到WEBView的JS調(diào)用也需要保證寫的接口方法不混淆
下面貼出網(wǎng)上搜集到的i自定義混淆的一些資料(全部是在該文件下的設(shè)置),大概了解一下,以后用到可以去翻翻.(這些都是例子,具體要根據(jù)自己的項(xiàng)目結(jié)構(gòu)去設(shè)置)**
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in C:\Users\Administrator\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.## For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface# class:
-keepclassmembers class fqcn.of.javascript.interface.for.webview { public *;}
# 有用到WEBView的JS調(diào)用接口不被混淆
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
public *;
}
#指定代碼的壓縮級別
-optimizationpasses 5
#包明不混合大小寫
-dontusemixedcaseclassnames
#不去忽略非公共的庫類
-dontskipnonpubliclibraryclasses
#優(yōu)化 不優(yōu)化輸入的類文件
-dontoptimize
#預(yù)校驗(yàn)
-dontpreverify
#混淆時(shí)是否記錄日志
-verbose
# 混淆時(shí)所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#保護(hù)注解
-keepattributes *Annotation*
# 保持哪些類不被混淆
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service 0
-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
#如果有引用v4包可以添加下面這行
-keep public class * extends android.support.v4.app.Fragment
#忽略警告
-ignorewarning
#apk 包內(nèi)所有 class 的內(nèi)部結(jié)構(gòu)
-dump class_files.txt
#未混淆的類和成員
-printseeds seeds.txt
#列出從 apk 中刪除的代碼
-printusage unused.txt
#混淆前后的映射
-printmapping mapping.txt
#混淆保護(hù)自己項(xiàng)目的部分代碼以及引用的第三方j(luò)ar包library
-libraryjars libs/umeng
-analytics-v5.2.4.jar
sdk-v1.0.0.jar,look-v1.0.1.jar
-libraryjars libs/sdk-v1.0.0.jar
-libraryjars libs/look-v1.0.1.jar
#忽略警告
-dontwarn com.lippi.recorder.utils**
#保留一個(gè)完整的包
-keep class com.lippi.recorder.utils.** {
*;
}
-keep class com.lippi.recorder.utils.AudioRecorder{
*;
}
#如果引用了v4或者v7包
-dontwarn android.support.**
#所有View的子類及其子類的get考廉、set方法都不進(jìn)行混淆
-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*(...);
}
#保持 native 方法不被混淆
-keepclasseswithmembernames class * {
native <methods>;
} #保持自定義控件類不被混淆
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
#保持Activity中參數(shù)類型為View的所有方法
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
#保持 Parcelable 不被混淆
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
#保持 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;
!static !transient <fields>;
!private <fields>;
!private <methods>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
#保持枚舉 enum 類不被混淆 如果混淆報(bào)錯(cuò)秘豹,建議直接使用上面的-keepclassmembers class * implements java.io.Serializable即可
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keepclassmembers class * {
public void *ButtonClicked(android.view.View);
}
#不混淆資源類
-keepclassmembers class **.R$* {
public static <fields>;
}
#不混淆所有的com.czy.bean包下的類和這些類的所有成員變量
-keep class czy.**{
*;
}
#避免混淆泛型 如果混淆報(bào)錯(cuò)建議關(guān)掉
–keepattributes Signature
#移除log 測試了下沒有用還是建議自己定義一個(gè)開關(guān)控制是否輸出日志
-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(...);
}
#如果用用到Gson解析包的,直接添加下面這幾行就能成功混淆昌粤,不然會報(bào)錯(cuò)既绕。
-libraryjars libs/gson-2.2.2.jar
-keepattributes Signature
-keep class sun.misc.Unsafe {
*;
}
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** {
*;
}
接下來說說怎么打包
一般的簽名打一個(gè)包,其實(shí)沒什么,就簽名-->打包
這里其實(shí)主要的問題是一個(gè)多渠道打包的問題,我目前只會一種方法,就是通過gradle配置,聽朋友說還有一種幾百個(gè)包,三分鐘搞定的,還沒有研究.
接下來我就具體總結(jié)一下通過gradle配置文件,進(jìn)行多渠道打包的問題,(一次打五六個(gè)包,幾分鐘搞定,其實(shí)也挺快的!)
** 讓我們以友盟統(tǒng)計(jì)為例**
- 首先我們現(xiàn)在Androidmaifest.xml文件里的application標(biāo)簽下,添加一個(gè)** meta-data**標(biāo)簽,如下圖所示:
這里用 ** ${ } ** 引用,方便我們在build中,動態(tài)配置不同的打包渠道
-
我們打開要打包的module下的build配置文件
這里會有兩個(gè)方法,一個(gè)普通方法,一個(gè)快捷方法
先說說普通方法,如下所示:
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"]
}
...
...
...
}
** UMENG_CHANNEL_VALUE **,就是動態(tài)修改Androidmanifest中的value,分不同的渠道,比較麻煩,主題內(nèi)容重復(fù)
快捷的方法就是把主題內(nèi)容抽出來單獨(dú)寫了一個(gè)方法:productFlavors { wandoujia {} baidu {} c360 {} ... ... ... productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] } }
配置好以后,就是編譯打包了,首先** 要配置好gradle的環(huán)境變量** 方便我們在Terminal的方式(cmd應(yīng)該也可以,沒試過),運(yùn)行打包命令,如果不知道的話,我先貼出配置方法吧(其實(shí)跟java配置環(huán)境變量一樣一樣的)
先找到gralde的根目錄啄刹,在系統(tǒng)變量里添加兩個(gè)環(huán)境變量:
變量名為:GRADLE_HOME,變量值就為gradle的根目錄凄贩;
所以變量值為:C:\Users\zilong\.gradle\wrapper\dists\gradle-2.1-all\27drb4udbjf4k88eh2ffdc0n55\gradle-2.1
還有一個(gè)在系統(tǒng)變量里PATH里面添加gradle的bin目錄
我的就是C:\Users\zilong\.gradle\wrapper\dists\gradle-2.1-all\27drb4udbjf4k88eh2ffdc0n55\gradle-2.1\bin
這里配置完成了鸵膏,接著在Terminal中敲下 ** gradle assembleRelease **就可以一次性生成所有的渠道包了。
所有生成的apk在項(xiàng)目的 ** build\outputs\apk **下怎炊。
如果想生成單個(gè)渠道的包怎么辦呢?不怕,我們有單個(gè)報(bào)的命令 ** gradle assembleWandoujiaRelease **,這樣就可以了.當(dāng)然這是豌豆莢的,百度,360,以此類推嘍~~~,如果不想用命令行怎么辦,不怕,我們as有這個(gè)功能,當(dāng)我們配置好參數(shù)以后,打開as右側(cè)的Gradle project面板,如下圖所示:
接下來只要雙擊想要打包的渠道,就可以打包了,方便吧!!!