0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Android編譯優(yōu)化之混淆配置

哆啦安全 ? 來源:虎哥Lovedroid ? 2023-12-21 09:21 ? 次閱讀

Android編譯優(yōu)化之混淆配置

背景

為了使用java8及后續(xù)java新版本的特性,Google增加了一步編譯過程—脫糖(desugaring),但這一步會導致更長的編譯時間,這也是為什么Google會推出D8和R8編譯器來優(yōu)化編譯速度。

什么是脫糖?

脫糖即在編譯階段將在語法層面一些底層字節(jié)碼不支持的特性轉換為基礎的字節(jié)碼結構,(比如 List 上的泛型脫糖后在字節(jié)碼層面實際為 Object); Android 工具鏈對 Java8 語法特性脫糖的過程可謂豐富多彩,當然他們的最終目的是一致的:使新的語法可以在所有的設備上運行。

D8

D8的功能是將Java字節(jié)碼轉化成dex代碼,D8作為DX的一個替代方案。編譯流程如下圖所示:

eccf159c-9f9d-11ee-8b88-92fbcf53809c.png

D8

Android Studio 3.1版本開始,將D8作為默認的Dex編譯器。如果想關閉D8,可以在gradle.properties里添加如下配置:

android.enableD8=false
android.enableD8.desugaring=false

開啟D8的好處

?編譯更快、時間更短

?DEX編譯時占用內容更小

?.dex文件更小

?D8編譯的.dex文件擁有相同或者更好的運行性能

如果你的工程已經(jīng)使用Java 8盡可能開啟D8編譯,不然可能會出現(xiàn)編譯錯誤。

R8

R8作為原本Proguard 壓縮與優(yōu)化(minification、shrinking、optimization)部分的替代品,依然使用與Proguard一樣的keep規(guī)則,是新一代的代碼壓縮工具。 R8之前采用D8+Proguard的形式構建,R8則將混淆和D8工具進行整合,目的是加速構建時間和減少輸出apk的大小。

ecebad7e-9f9d-11ee-8b88-92fbcf53809c.png

R8

Gradle插件版本達到3.4.0及以上,默認會開始R8進行代碼優(yōu)化。如果你不想開啟R8,可以在gradle.properties里添加如下配置:

android.enableR8=false

開啟R8的好處

?代碼縮減:規(guī)避64引用限制

?資源縮減:移除不使用的資源

?混淆代碼:減小DEX文件大小

?優(yōu)化代碼:進一步減小DEX文件大小

相關評測報告

ed0349de-9f9d-11ee-8b88-92fbcf53809c.png

D8R8評測報告

AS多模塊混淆配置

AS多模塊下,我們可以采用各個模塊單獨配置方式,即proguard文件配置在各個模塊下,在各自的build.gradle文件中引入; 也可以采用下方集中配置方式,將各模塊的proguard文件集中配置到一個文件夾下,然后在app模塊中集中引入所依賴的模塊的proguard文件。 下面以cmcc_service這個app模塊為例加以說明,

buildTypes{
release{
minifyEnabledtrue//開啟混淆
shrinkResourcestrue//無用資源去除
zipAlignEnabledtrue
proguardFilesgetDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro',
'../proguardDefine/common-rules.pro','../proguardDefine/live_lib-rules.pro',
'../proguardDefine/gs_api_adapter-rules.pro','../proguardDefine/cmcc_service.pro',
'../proguardDefine/lib_voiceassistant-rules.pro','../proguardDefine/cmcc_softprobe-rules.pro'
if(propertyHaveSigningConfigs)
signingConfigsigningConfigs.release
}
}

其中,proguard-android-optimize.txt是android默認的一些通用混淆規(guī)則,proguard-rules.pro是app代碼的混淆規(guī)則,proguardDefine文件夾下所依賴模塊統(tǒng)一放置proguard規(guī)則的地方。

注意:引入的三方libs,一般都配有響應的proguard文件,所以不需要再重復配置,gradle編譯時會將相關文件 proguard文件合并到一個configuration.txt文件中

ed1b5dda-9f9d-11ee-8b88-92fbcf53809c.png

configuration位置

proguard-android-optimize.txt

#禁用一些代碼簡化和優(yōu)化,以及字段和類合并
-optimizations!code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
#運行優(yōu)化passes的數(shù)量為5,數(shù)值越高,混淆效果越好,但耗時也更長
-optimizationpasses5
#允許訪問和修改保護代碼
-allowaccessmodification

#不允許使用大小寫混合的類名
-dontusemixedcaseclassnames
#不跳過非公共庫類
-dontskipnonpubliclibraryclasses
#詳細輸出
-verbose

#保留一些反射所需的屬性
-keepattributes*Annotation*,Signature,InnerClasses,EnclosingMethod
#保留以下三個類及其公共成員
-keeppublicclasscom.google.vending.licensing.ILicensingService
-keeppublicclasscom.android.vending.licensing.ILicensingService
-keeppublicclasscom.google.android.vending.licensing.ILicensingService
#忽略以下類,不輸出note信息
-dontnotecom.android.vending.licensing.ILicensingService
-dontnotecom.google.vending.licensing.ILicensingService
-dontnotecom.google.android.vending.licensing.ILicensingService

#對于本地方法,參見http://proguard.sourceforge.net/manual/examples.html#native
#保留包含native方法的類和方法
-keepclasseswithmembernames,includedescriptorclassesclass*{
native;
}
#保留公共的View子類的set和get方法
#以便于使用屬性動畫
-keepclassmemberspublicclass*extendsandroid.view.View{
voidset*(***);
***get*();
}
#保留Activity中可用于XML屬性onClick中的方法
-keepclassmembersclass*extendsandroid.app.Activity{
publicvoid*(android.view.View);
}
#對于枚舉類,參見http://proguard.sourceforge.net/manual/examples.html#enumerations
#保留枚舉類成員
-keepclassmembersenum*{
publicstatic**[]values();
publicstatic**valueOf(java.lang.String);
}
#保留實現(xiàn)Parcelable接口的類的CREATOR靜態(tài)成員
-keepclassmembersclass*implementsandroid.os.Parcelable{
publicstaticfinal**CREATOR;
}
#保留JavaScript接口方法上的注解
-keepclassmembersclass*{
@android.webkit.JavascriptInterface;
}
#支持庫包含對新平臺版本的引用
#在應用鏈接舊版平臺版本時,不要發(fā)出警告,因為它們是安全的
-dontnoteandroid.support.**
-dontnoteandroidx.**
-dontwarnandroid.support.**
-dontwarnandroidx.**
#該類已棄用,但仍然保留用于向后兼容
-dontwarnandroid.util.FloatMath
#這段混淆規(guī)則用于保護使用了@Keep注解的類和成員不被混淆,以及忽略特定的冗余類。
-keepclassandroid.support.annotation.Keep
-keepclassandroidx.annotation.Keep
#保留使用了@Keep注解的類和接口的所有成員
-keep@android.support.annotation.Keepclass*{;}
-keep@androidx.annotation.Keepclass*{;}
#保留使用了@Keep注解的類的方法
-keepclasseswithmembersclass*{
@android.support.annotation.Keep;
}
-keepclasseswithmembersclass*{
@androidx.annotation.Keep;
}
#保留使用了@Keep注解的類的字段
-keepclasseswithmembersclass*{
@android.support.annotation.Keep;
}
-keepclasseswithmembersclass*{
@androidx.annotation.Keep;
}
#保留使用了@Keep注解的類的構造方法
-keepclasseswithmembersclass*{
@android.support.annotation.Keep(...);
}
-keepclasseswithmembersclass*{
@androidx.annotation.Keep(...);
}
#忽略特定的冗余類
#android.jar和org.apache.http.legacy.jar中的類重復
-dontnoteorg.apache.http.**
-dontnoteandroid.net.http.**
#android.jar和core-lambda-stubs.jar中的類重復
-dontnotejava.lang.invoke.**

一些三方自帶混淆規(guī)則

這些規(guī)則同樣合并到了configuration.txt文件中retrofit2混淆規(guī)則

#Theproguardconfigurationfileforthefollowingsectionis/home/cl/.gradle/caches/transforms-3/29b6aa006718d6829551a18646bf70bb/transformed/rules/lib/META-INF/proguard/retrofit2.pro
#Retrofitdoesreflectionongenericparameters.InnerClassesisrequiredtouseSignatureand
#EnclosingMethodisrequiredtouseInnerClasses.
-keepattributesSignature,InnerClasses,EnclosingMethod

#Retainservicemethodparameterswhenoptimizing.
-keepclassmembers,allowshrinking,allowobfuscationinterface*{
@retrofit2.http.*;
}

#Ignoreannotationusedforbuildtooling.
-dontwarnorg.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

#IgnoreJSR305annotationsforembeddingnullabilityinformation.
-dontwarnjavax.annotation.**

#GuardedbyaNoClassDefFoundErrortry/catchandonlyusedwhenontheclasspath.
-dontwarnkotlin.Unit

#Top-levelfunctionsthatcanonlybeusedbyKotlin.
-dontwarnretrofit2.-KotlinExtensions

#Endofcontentfrom/home/cl/.gradle/caches/transforms-3/29b6aa006718d6829551a18646bf70bb/transformed/rules/lib/META-INF/proguard/retrofit2.pro

RxJava2RxAndroid混淆規(guī)則

-dontwarnjava.util.concurrent.Flow*

Okhttp3混淆規(guī)則

#Theproguardconfigurationfileforthefollowingsectionis/home/cl/.gradle/caches/transforms-3/af3ecb4c3ae4accf6423845d738f047d/transformed/rules/lib/META-INF/proguard/okhttp3.pro
#JSR305annotationsareforembeddingnullabilityinformation.
-dontwarnjavax.annotation.**

#Aresourceisloadedwitharelativepathsothepackageofthisclassmustbepreserved.
-keepnamesclassokhttp3.internal.publicsuffix.PublicSuffixDatabase

#AnimalSniffercompileOnlydependencytoensureAPIsarecompatiblewitholderversionsofJava.
-dontwarnorg.codehaus.mojo.animal_sniffer.*

#OkHttpplatformusedonlyonJVMandwhenConscryptdependencyisavailable.
-dontwarnokhttp3.internal.platform.ConscryptPlatform

#Endofcontentfrom/home/cl/.gradle/caches/transforms-3/af3ecb4c3ae4accf6423845d738f047d/transformed/rules/lib/META-INF/proguard/okhttp3.pro

更多可能用到的混淆配置

#指定不去忽略非公共庫的類
-dontskipnonpubliclibraryclasses
#指定不去忽略非公共庫的成員
-dontskipnonpubliclibraryclassmembers
#混淆時不做預校驗
-dontpreverify
#忽略警告
-ignorewarnings
#保留代碼行號,方便異常信息的追蹤
-keepattributesSourceFile,LineNumberTable
#appcompat庫不做混淆
-keepclassandroidx.appcompat.**
#保留AndroidManifest.xml文件:防止刪除AndroidManifest.xml文件中定義的組件
-keeppublicclass*extendsandroid.app.Fragment
-keeppublicclass*extendsandroid.app.Activity
-keeppublicclass*extendsandroid.app.Application
-keeppublicclass*extendsandroid.app.Service
-keeppublicclass*extendsandroid.content.BroadcastReceiver
-keeppublicclass*extendsandroid.content.ContentProvider
-keeppublicclass*extendsandroid.preference.Preference
-keeppublicclass*extendsandroid.view.View

#保留序列化,例如Serializable接口
-keepclassmembersclass*implementsjava.io.Serializable{
staticfinallongserialVersionUID;
privatestaticfinaljava.io.ObjectStreamField[]serialPersistentFields;
privatevoidwriteObject(java.io.ObjectOutputStream);
privatevoidreadObject(java.io.ObjectInputStream);
java.lang.ObjectwriteReplace();
java.lang.ObjectreadResolve();
}

#帶有Context、View、AttributeSet類型參數(shù)的初始化方法
-keepclasseswithmembersclass*{
public(android.content.Context);
}
-keepclasseswithmembersclass*{
public(android.content.Context,android.util.AttributeSet);
}
-keepclasseswithmembersclass*{
public(android.content.Context,android.util.AttributeSet,int);
}
-keepclassmembersclass*extendsandroid.app.Activity{
publicvoid*(android.view.View);
}

#保留資源R類
-keepclass**.R$*{*;}

#避免回調函數(shù)onXXEvent混淆
-keepclassmembersclass*{
void*(**On*Event);
void*(**On*Listener);
void*(**on*Changed);
}

#業(yè)務實體不做混淆,避免gson解析錯誤
-dontwarncom.grandstream.convergentconference.entity.**
-keepclasscom.grandstream.convergentconference.entity.**{*;}

#Rxjava、RxAndroid,官方ReadMe文檔中說明無需特殊配置
-dontwarnjava.util.concurrent.Flow*
#okhttp3、okio、retrofit,jar包中已包含相關proguard規(guī)則,無需配置
#其他一些配置

Android.bp混淆配置

android_app{
name:"MyApp",
package_name:"com.example.myapp",
srcs:["java/**/*.java"],
manifest:"AndroidManifest.xml",
dex_preopt:{
enabled:true,
},
apk_cert_permissions:[
"android.permission.ACCESS_FINE_LOCATION",
"android.permission.RECORD_AUDIO",
"android.permission.READ_CONTACTS",
],
certificates:["platform"],
resource_files:["res/**/*"],
enable_proguard:true,
proguard_flags:["proguard-android.txt"],
dex_preopt_image_dir:"target/product/${TARGET_PRODUCT}/obj/dex_preopt_image",
}

其中,enable_proguard 設置為 true 表示啟用代碼和資源混淆,proguard_flags 指定了 Proguard 混淆規(guī)則文件,可以在文件中指定代碼和資源混淆規(guī)則。 resource_files 指定了應用程序的資源文件,包括 AndroidManifest.xml 文件。

android.mk混淆配置

LOCAL_PROGUARD_ENABLED:=obfuscationoptimization

LOCAL_PROGUARD_FLAG_FILES:=proguard.flags
ifeq(eng,$(TARGET_BUILD_VARIANT))
LOCAL_PROGUARD_FLAG_FILES+=proguard-test.flags
else
LOCAL_PROGUARD_FLAG_FILES+=proguard-release.flags
endif

LOCAL_PROGUARD_ENABLED有以下幾種配置:

1.LOCAL_PROGUARD_ENABLED := disabled:禁用混淆。

2.LOCAL_PROGUARD_ENABLED := obfuscate:只開啟代碼混淆,不進行優(yōu)化。

3.LOCAL_PROGUARD_ENABLED := optimize:只開啟優(yōu)化,不進行代碼混淆。

4.LOCAL_PROGUARD_ENABLED := obfuscate optimize:同時開啟代碼混淆和優(yōu)化。

編譯系統(tǒng)默認應該會加載一個android通用的混淆文件,LOCAL_PROGUARD_FLAG_FILES用于指定app特定的proguard文件。 如果我們不太會配置這些選項,可以去查看原生應用的混淆配置,這對你會有很大啟發(fā)。

混淆堆棧還原

使用 android 自帶的混淆堆棧還原工具 proguardgui 解決

Android/Sdk/tools/proguard/bin$ls
proguard.shproguardgui.shretrace.sh
/Android/Sdk/tools/proguard/bin$./proguardgui.sh

腳本運行后會打開 ProGuard 調試界面

ed3192b2-9f9d-11ee-8b88-92fbcf53809c.png

proguard gui tools

填寫混淆前后的映射文件 mapping.txt 和需要還原的 logcat 異常日志,點擊 Retrace 按鈕就能還原混淆前的異常信息

結論

總之,一些通用混淆規(guī)則Android已經(jīng)幫我寫好了,我們關心的可能就是我們自己開發(fā)的那部分代碼的混淆規(guī)則,混淆工作做的好有很多好處: 代碼更安全、包體積更小、運行速度更快,但是混淆也會帶來意想不到的運行異常,希望你做好測試,希望你盡快用起來。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • Android
    +關注

    關注

    12

    文章

    3917

    瀏覽量

    127036
  • JAVA
    +關注

    關注

    19

    文章

    2952

    瀏覽量

    104477
  • 代碼
    +關注

    關注

    30

    文章

    4722

    瀏覽量

    68229
  • 編譯
    +關注

    關注

    0

    文章

    648

    瀏覽量

    32774

原文標題:Android編譯優(yōu)化之混淆配置

文章出處:【微信號:哆啦安全,微信公眾號:哆啦安全】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Build settings探究編譯優(yōu)化介紹

    Build settings探究編譯優(yōu)化
    發(fā)表于 06-19 10:17

    Android內核編譯教程

    標準的Linux開發(fā)流程一樣,Android平臺開發(fā)的一個很重要的基礎工作就是對其內核的編譯和移植。本文結合Android的開發(fā)文檔以及本人的實踐經(jīng)驗,簡單介紹了Android內核的
    發(fā)表于 06-22 09:11 ?93次下載

    Android編譯工具

    Android編譯工具
    發(fā)表于 12-17 15:59 ?21次下載

    第10章Linux及Android操作系統(tǒng)的編譯

    10.1 Android系統(tǒng)架構 10.2 Ubuntu編譯環(huán)境配置 10.3 快速入門與預編譯二進制文件 10.4 從源代碼構建
    發(fā)表于 04-11 14:59 ?0次下載

    Android源代碼編譯

    Android源代碼編譯
    發(fā)表于 10-24 09:30 ?5次下載
    <b class='flag-5'>Android</b>源代碼<b class='flag-5'>編譯</b>

    fireflyAIO-3399C主板編譯 Android8.1 固件簡介

    編譯 Android8.1 固件 準備工作 編譯 Android 對機器的配置要求較高
    的頭像 發(fā)表于 12-13 10:31 ?1133次閱讀

    fireflyAIO-3288C主板編譯Android固件簡介

    編譯 Android 對機器的配置要求較高
    的頭像 發(fā)表于 12-16 14:53 ?1008次閱讀

    fireflyCORE-RK3328主板JD4編譯 Android 8.1介紹

    編譯 Android 8.1 準備 硬件配置
    的頭像 發(fā)表于 12-18 14:35 ?1347次閱讀

    fireflyROC-RK3399主板PC編譯Android 8.1簡介

    編譯 Android 8.1 準備 硬件配置 編譯 Android 8.1 開發(fā)環(huán)境硬件配置
    的頭像 發(fā)表于 12-20 10:38 ?2922次閱讀

    fireflyROC-RK3328主板編譯Android 7.1簡介

    編譯 Android 7.1 開發(fā)環(huán)境硬件配置建議
    的頭像 發(fā)表于 12-21 10:52 ?2519次閱讀

    fireflyAIO-3128C主板編譯Android 固件介紹

    編譯 Android 對機器的配置要求較高: 64 位 CPU 16GB 物理內存+交換內存
    的頭像 發(fā)表于 12-24 09:04 ?1131次閱讀

    fireflyAIO-3399J編譯 Android 固件簡介

    編譯 Android 固件 準備工作 編譯 Android 對機器的配置要求較高: 64 位 CPU 16GB 物理
    的頭像 發(fā)表于 12-24 11:03 ?1306次閱讀

    fireflyAIO-3288J主板編譯Android固件簡介

    編譯 Android 固件 準備工作 編譯 Android 對機器的配置要求較高: 64 位 CPU 16GB 物理
    的頭像 發(fā)表于 12-26 14:44 ?1337次閱讀

    深入淺出編譯優(yōu)化選項(下)

    在《深入淺出編譯優(yōu)化選項(上)》中,我們介紹了如何在IAR Embedded Workbench編譯器中進行編譯優(yōu)化等級
    的頭像 發(fā)表于 04-21 10:19 ?1204次閱讀

    APP混淆實戰(zhàn)(Java/so代碼混淆)

    Android App Bundle混淆加密加殼加固保護的解決方案(過Google App上架審核)最全Android及資源混淆方法匯總(無需加固節(jié)約成本并將APP上架Google P
    的頭像 發(fā)表于 06-29 15:42 ?855次閱讀
    APP<b class='flag-5'>混淆</b>實戰(zhàn)(Java/so代碼<b class='flag-5'>混淆</b>)