Android Studio混淆打包

前兩周應業務需要研究了一下混淆打包和sdk混淆技術。在此記錄下心得。

1.apk混淆打包

如果要對apk進行混淆,你要先告知gradle這個app需要混淆,并告知其混淆規則。

  • 告知gradle需要混淆的代碼
    在Project/app/build.gradle中把minifyEnabled設置為true,表示說打包時需要執行混淆操作。如下代碼:
buildTypes {
    release {
      // 混淆
      minifyEnabled true
      // Zipalign優化
      zipAlignEnabled true
      // 移除無用的resource文件
      shrinkResources true
      // 前一部分代表系統默認的android程序的混淆文件,該文件已經包含了基本的混淆聲明,后一個文件是自己的定義混淆文件
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
      signingConfig signingConfigs.release
    }
}
  • 編寫混淆規則
    正如上方的代碼,proguard-rules.txt就是寫好混淆規則的文件。gradle根據這個文件設定的混淆規則對apk進行打包。
progard-rules存放位置

2.混淆規則注意事項

網絡上有許多混淆規則的代碼,看官方文檔最好:gradle example,這里面有對各種sdk和library混淆時候時已經寫好的混淆代碼,直接去抄里面的示例代碼就好。
混淆時最麻煩的幾點就是:

  • 第三方lib包的混淆(不再有警告提醒)
    比如對apache的common包,dom4j的混淆,可以不用混淆
#############################################
# 不警告
-dontwarn org.dom4j.**
# 不混淆
-keep class org.dom4j.** { *; }
-dontwarn org.apache.**
-keep class org.apache.** { *; }
-dontwarn org.xmlpull.**
-keep class org.xmlpull.** { *; }
-dontwarn com.jcraft.**
-keep class com.jcraft.** { *; }
  • 某個包下的類不用混淆
#-------------處理本應用不需要混淆的代碼-------------------
keep class com.android.smarttouch.ctrl.** { *; }
  • android常用的混淆配置
## 對于一些基本指令的添加############################################### 代碼混淆壓縮比,在0~7之間,默認為5,一般不做修改
-optimizationpasses 5
# 混合時不使用大小寫混合,混合后的類名為小寫
-dontusemixedcaseclassnames
# 指定不去忽略非公共庫的類
-dontskipnonpubliclibraryclasses
# 這句話能夠使我們的項目混淆后產生映射文件# 包含有類名->混淆后類名的映射關系
-verbose
# 指定不去忽略非公共庫的類成員
-dontskipnonpubliclibraryclassmembers
# 不做預校驗,preverify是proguard的四個步驟之一,Android不需要preverify,去掉這一步能夠加快混淆速度。
-dontpreverify
# 保留Annotation不混淆
-keepattributes *Annotation*,InnerClasses
# 避免混淆泛型
-keepattributes Signature
# 拋出異常時保留代碼行號
-keepattributes SourceFile,LineNumberTable
# 指定混淆是采用的算法,后面的參數是一個過濾器
# 這個過濾器是谷歌推薦的算法,一般不做更改
-optimizations !code/simplification/cast,!field/*,!class/merging/*
############################################### Android開發中一些需要保留的公共部分############################################### 保留我們使用的四大組件,自定義的Application等等這些類不被混淆# 因為這些子類都有可能被外部調用
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-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 * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
# 保留support下的所有類及其內部類
-keep class android.support.** {*;}
# 保留繼承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**
# 保留R下面的資源
-keep class **.R$* {*;}
# 保留本地native方法不被混淆
-keepclasseswithmembernames class * {    native <methods>;}
# 保留在Activity中的方法參數是view的方法,
# 這樣以來我們在layout中寫的onClick就不會被影響-keepclassmembers class * extends android.app.Activity{    public void *(android.view.View);}
# 保留枚舉類不被混淆
-keepclassmembers enum * {    public static **[] values();    public static ** valueOf(java.lang.String);}
# 保留我們自定義控件(繼承自View)不被混淆
-keep public class * extends android.view.View{    *** get*();    void set*(***);    public <init>(android.content.Context);    public <init>(android.content.Context, android.util.AttributeSet);    public <init>(android.content.Context, android.util.AttributeSet, int);}
# 保留Parcelable序列化類不被混淆
-keep class * implements android.os.Parcelable {    public static final android.os.Parcelable$Creator *;}
# 保留Serializable序列化的類不被混淆
-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();}
# 對于帶有回調函數的onXXEvent、**On*Listener的,不能被混淆
-keepclassmembers class * {    void *(**On*Event);    void *(**On*Listener);}
# webView處理,項目中沒有使用到webView忽略即可
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#    public *;
#}
#-keepclassmembers class * extends android.webkit.webViewClient {
#    public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
#    public boolean *(android.webkit.WebView, java.lang.String);
#}
#-keepclassmembers class * extends android.webkit.webViewClient {
#    public void *(android.webkit.webView, jav.lang.String);
#}
# 移除Log類打印各個等級日志的代碼,打正式包的時候可以做為禁log使用,這里可以作為禁止log打印的功能使用
# 記得proguard-android.txt中一定不要加-dontoptimize才起作用
# 另外的一種實現方案是通過BuildConfig.DEBUG的變量來控制
#-assumenosideeffects class android.util.Log {
#    public static int v(...);
#    public static int i(...);
#    public static int w(...);
#    public static int d(...);
#    public static int e(...);

本站文章為 寶寶巴士 SD.Team SuperDo.Preacher原創,轉載務必在明顯處注明:(作者官方網站: 寶寶巴士 ) __轉載自【寶寶巴士SuperDo團隊】原文鏈接: http://www.lxweimin.com/p/d7b7e903cfa7

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容