Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android產品研發(六)--)Apk混淆

android產品研發(六)--)Apk混淆

編輯:關於Android編程

前面一篇文章中我們講解了android裡面的多渠道打包,對於大型的app來說,幾百個上千個渠道包都是很正常的事,所以效率定制化是一件很重要的事。主要講解了三種多渠道打包方式,並分析了其各自的利弊,在各自產品多渠道打包的時候,可以根據自身的產品需求選擇相應的打包方式。

而本文主要講解Apk的混淆,這裡的混淆分為兩種代碼混淆和資源文件混淆。實際的產品研發中為了防止自己的勞動成果被別人竊取,混淆代碼能有效防止apk文件被反編譯,進而查看源代碼。說來慚愧,作為互聯網創業公司的我們也確實對競品Apk反編譯研究過,如果Apk混淆之後確實對理解源碼的業務流程造成了困擾,這也從側面說明了Apk混淆的重要性。

所以對於android apk安裝文件來說如何混淆代碼實現對apk文件的保護是一個很重要的問題,而android提供了Progurd方式來混淆apk中的代碼,其核心的邏輯是在代碼層將一些易懂的源代碼類名,方法名稱替換成毫無意義的a、b、c、d…,這樣當別人反編譯出你的Apk文件時,看到的源代碼也無法還原其本身的邏輯。

下面我們將分別介紹代碼混淆與資源文件混淆具體實踐。

- 代碼混淆-Progurd

下面來總結以下混淆代碼的步驟:

在android studio的android項目中找到module的gradle配置文件,添加proguard配置
buildTypes {
        debug {
            // 顯示Log
            buildConfigField "boolean", "LOG_DEBUG", "true"
            //混淆
            minifyEnabled false
            //Zipalign優化
            zipAlignEnabled true
            // 移除無用的resource文件
            shrinkResources true
            //加載默認混淆配置文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //簽名
            signingConfig signingConfigs.debug
        }
        release {
            // 不顯示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            //混淆
            minifyEnabled true
            //Zipalign優化
            zipAlignEnabled true
            // 移除無用的resource文件
            shrinkResources true
            //加載默認混淆配置文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //簽名
            signingConfig signingConfigs.relealse
        }
    }
找到項目中的proguard-rules.pro文件,該文件就是我們的混淆配置文件

這裡寫圖片描述

3.編寫proguard-rules.pro文件,添加混淆配置

(1)proguard混淆語法

-libraryjars class_path 應用的依賴包,如android-support-v4  
-keep [,modifier,...] class_specification 這裡的keep就是保持的意思,意味著不混淆某些類 
-keepclassmembers [,modifier,...] class_specification 同樣的保持,不混淆類的成員  
-keepclasseswithmembers [,modifier,...] class_specification 不混淆類及其成員  
-keepnames class_specification 不混淆類及其成員名  
-keepclassmembernames class_specification 不混淆類的成員名  
-keepclasseswithmembernames class_specification 不混淆類及其成員名  
-assumenosideeffects class_specification 假設調用不產生任何影響,在proguard代碼優化時會將該調用remove掉。如system.out.println和Log.v等等  
-dontwarn [class_filter] 不提示warnning  

(2)混淆原則

jni方法不可混淆
反射用到的類不混淆(否則反射可能出現問題)
AndroidMainfest中的類不混淆,四大組件和Application的子類和Framework層下所有的類默認不會進行混淆
Parcelable的子類和Creator靜態成員變量不混淆,否則會產生android.os.BadParcelableException異常
使用GSON、fastjson等框架時,所寫的JSON對象類不混淆,否則無法將JSON解析成對應的對象
使用第三方開源庫或者引用其他第三方的SDK包時,需要在混淆文件中加入對應的混淆規則
有用到WEBView的JS調用也需要保證寫的接口方法不混淆

(3)第三方庫的混淆原則

一般的第三方庫都有自身的混淆方案,可直接引用其自身的混淆配置即可
若無混淆配置,一般的可配置不混淆第三方庫

(4)最後帖上我們項目中實際的混淆方案

# Glide圖片庫的混淆處理
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
    **[] $VALUES;
    public *;
}

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

# 高德地圖混淆腳本
-keep class com.android.support.**{ *; }
-keep interface android.support.v4.app.**{ *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment

-dontwarn com.amap.api.**
-dontwarn com.a.a.**
-dontwarn com.autonavi.**
-keep class com.amap.api.** {*;}
-keep class com.autonavi.** {*;}
-keep class com.a.a.** {*;}

# Gson混淆腳本
-keep class com.google.gson.stream.** {*;}
-keep class com.youyou.uuelectric.renter.Network.user.** {*;}

# butterknife混淆腳本
-dontwarn butterknife.internal.**
-keep class **$$ViewInjector { *; }
-keepnames class * { @butterknife.InjectView *;}

# -------------系統類不需要混淆 --------------------------
-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
-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.support.**
-keep public class com.android.vending.licensing.ILicensingService

-keepclasseswithmembernames class * { # 保持native方法不被混淆
    native ;
}
-keepclasseswithmembernames class * { # 保持自定義控件不被混淆
    public (android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * { # 保持自定義控件不被混淆
    public (android.content.Context, android.util.AttributeSet, int);
}
-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 *;
}

# --------- 忽略異常提示 --------------------
-dontwarn butterknife.internal.**
-dontwarn com.alipay.**
-dontwarn com.mikepenz.**
-dontwarn org.apache.**
-dontwarn com.amap.**
-dontwarn com.android.volley.**
-dontwarn com.rey.**
-dontwarn com.testin.**
-dontwarn jp.wasabeef.**

# ---------- 保持代碼 --------------
-keep class com.youyou.uuelectric.renter.Utils.** {*;}
-keep class it.neokree.** {*;}
-keep class org.apache.** {*;}
-keep class com.iflytek.** {*;}
-keep class com.google.protobuf.** { *; }
-keep class com.youyou.uuelectric.renter.pay.** {*;}

# ---------------- eventbus避免混淆 ------------
-keepclassmembers class ** {
    public void onEvent*(**);
    void onEvent*(**);
}


# --------------- 友盟統計避免混淆 -------------------------
-dontwarn android.support.v4.**
-dontwarn org.apache.commons.net.**
-dontwarn com.tencent.**
-keepclasseswithmembernames class * {
    native ;
}
-keepclasseswithmembernames class * {
    public (android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
    public (android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
-keepclasseswithmembers class * {
    public (android.content.Context);
}
-dontshrink
-dontoptimize
-dontwarn com.google.android.maps.**
-dontwarn android.webkit.WebView
-dontwarn com.umeng.**
-dontwarn com.tencent.weibo.sdk.**
-dontwarn com.facebook.**
-keep enum com.facebook.**
-keepattributes Exceptions,InnerClasses,Signature
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-keep public interface com.facebook.**
-keep public interface com.tencent.**
-keep public interface com.umeng.socialize.**
-keep public interface com.umeng.socialize.sensor.**
-keep public interface com.umeng.scrshot.**
-keep public class com.umeng.socialize.* {*;}
-keep public class javax.**
-keep public class android.webkit.**
-keep class com.facebook.**
-keep class com.umeng.scrshot.**
-keep public class com.tencent.** {*;}
-keep class com.umeng.socialize.sensor.**
-keep class com.tencent.mm.sdk.openapi.WXMediaMessage {*;}
-keep class com.tencent.mm.sdk.openapi.** implements com.tencent.mm.sdk.openapi.WXMediaMessage$IMediaObject {*;}
-keep class im.yixin.sdk.api.YXMessage {*;}
-keep class im.yixin.sdk.api.** implements im.yixin.sdk.api.YXMessage$YXMessageData{*;}
-keep public class [your_pkg].R$*{
    public static final int *;
}

# 熱修復混淆
-keep class * extends java.lang.annotation.Annotation
-keep class com.alipay.euler.andfix.** { *; }
-keepclasseswithmembernames class * {
    native ;
}

(5)混淆配置完成之後編譯混淆包,測試

有的時候混淆之後可能會出現一些奇形怪狀的bug,有條件的話,可以讓QA回滾一次混淆包的測試。

- 資源文件混淆-微信方案

前面我們說過本文主要講的是Apk的混淆,除了源代碼的混淆,還有資源文件的混淆。

去年微信推出了一個apk資源混淆方案,該方案的具體原理課參見:安裝包立減1M–微信Android資源混淆打包工具

在其文章中分析了資源文件混淆的幾種方案:

方案一:最簡單的方法,我們按照Proguard的做法,直接在源碼級別修改,將代碼以及xml的R.string.name中替換到R.string.a,icon.png重命名為a.png 然後再交給Android編譯。

方案二:根據Android的編譯流程,所有資源ID已經被編譯成32位int值。這說明我們並不需要去修改xml與java,因為在編譯過程已經被R.java所替換,我們直接修改resources.arsc的二進制數據,不改變打包流程,只要在生成resources.arsc之後修改它,同時重命名資源文件。

方案三:直接處理安裝包. 不依賴源碼,不依賴編譯過程,僅僅輸入一個安裝包,得到一個混淆包。

幾種方案的對比如下:
這裡寫圖片描述閱讀本文對Apk的混淆能有一個整體的認識。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved