android 代碼 混淆

       代碼混淆對於每個上線的應用來說,是安全方面最基本的操作。也是每個Android 開發者必備知識點,但是對於初學者來說這方面的內容很容易被忽略。畢竟不添加混淆 APP 也照樣可以跑起來。當然這樣的應用是很不安全的,利用 反編譯工具 我們可以輕鬆 看到 工程的源碼。很多信息就會直白的暴露別人面前。

  

上圖是 我利用反編譯工具 jadx-gui 查看的 我的一個 未經過 代碼混淆打包 的apk  的文件。 是不是看完心慌慌的,自己信心苦苦寫的代碼 就這樣完全的展示給別人看了。

如何 反編譯 得到 apk 中的源碼,可以查看這篇文章

https://blog.csdn.net/u010324235/article/details/83446655

接下來我們要介紹代碼 混淆

我們先看一下經過代碼混淆後的apk 反編譯後的代碼結構

  我們可以看到有些包名和類名都變成了abcd了 ,源碼中 也有很多 abcd  這樣一來 閱讀起來就很難了,即使拿到這樣的源碼也很難 看懂代碼中的內容,這就是代碼混淆的作用。

在開啓代碼混淆之前首先要思考一下,哪些代碼是不可以被混淆的,如上圖中,我們看到百度地圖中的內容就沒有被混淆,都是原原本本的類名和方法名。

首先第一個就是在AndroidManifest.xml中靜態註冊的四大組件 ,當然也包括自定義的application。因爲這些靜態註冊的組件如果被混淆了肯定就找不到了。

第二個 實現了 Serializable 的類不能被混淆,否則反序列化的時候要出錯。

第三個 support v4 和v7 還有 design 裏的內容不能被混淆,這是系統的內容。

第四個 自定義的view 不能被混淆, 不然我們在layout中使用view 的時候回找不到

第五個 泛型不能混淆

第六個 實體類不能被混淆,gson 會報錯

滴七個 引入的module jar lib 不能被混淆 一般使用第三方 jar 包網站中會說明 如何進行代碼混淆 

開啓代碼混淆 我們在 

build.gradle 文件中 設置minfyEnabled 爲 true

  release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

然後在  proguard-rules.pro 文件中keep 住我們 不需要混淆的地方

首先是每個apk都需要用到的 

#1.基本指令區
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose
-ignorewarning
-printmapping proguardMapping.txt
-optimizations !code/simplification/cast,!field/*,!class/merging/*
-keepattributes *Annotation*,InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable

#2.默認保留區
-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 * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
-keep class android.support.** {*;}

-keepclasseswithmembernames class * {
    native <methods>;
}
-keepclassmembers class * extends android.app.Activity{
    public void *(android.view.View);
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
-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);
}
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
-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();
}
-keep class **.R$* {
 *;
}

-keepclassmembers class * {
    void *(**On*Event);
}

#3.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);
}

然後是 第三方的 jar 官方文檔中有介紹的我們直接加載裏面就好

# 百度地圖
-keep class com.baidu.** {*;}
-keep class mapsdkvi.com.** {*;}
-dontwarn com.baidu.**

#極光推送
-dontoptimize
-dontpreverify

-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-keep class * extends cn.jpush.android.helpers.JPushMessageReceiver { *; }

-dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }

之後是 v4 v7 design

# support-v4
-dontwarn android.support.v4.**
-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class android.support.v4.** { *; }


# support-v7
-dontwarn android.support.v7.**
-keep class android.support.v7.internal.** { *; }
-keep interface android.support.v7.internal.** { *; }
-keep class android.support.v7.** { *; }

# support design
-dontwarn android.support.design.**
-keep class android.support.design.** { *; }
-keep interface android.support.design.** { *; }
-keep public class android.support.design.R$* { *; }

還有項目中可能用到的 框架

#glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
#arouter
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}

#Rxjava RxAndroid
-dontwarn rx.*
-dontwarn sun.misc.**

-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
   long producerIndex;
   long consumerIndex;
}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode producerNode;
}

-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode consumerNode;
}

# okhttp
-dontwarn com.squareup.okhttp.**
-keep class com.squareup.okhttp.{*;}
#retrofit
-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-dontwarn okio.**

#gson
-keep class com.google.gson.** {*;}
-keep class com.google.**{*;}
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }

還有就是我們需要把我們項目中國的實體類keep住 我們可以吧 javabean 都放在一個文件夾下面,然後用下面的 語句 就可以使得整個文件夾下面的實體類都不被混淆

#實體類
-keep class 所在文件夾路徑.** { *; }

還有就是一些引用的第三方jar並沒有文檔告訴我們怎麼混淆。我們可以直接使用包名

#jar 包
-keep class 包名.** { *; }

差不多就是上面這些 需要注意的地方千萬別漏掉 。歡迎補充。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章