找回密码
 会员注册
查看: 35|回复: 0

AndroidProguard混淆

[复制链接]

3

主题

0

回帖

10

积分

新手上路

积分
10
发表于 2024-9-3 10:27:30 | 显示全部楼层 |阅读模式
关于作者:CSDN内容合伙人、技术专家,从零开始做日活千万级APP。专注于分享各领域原创系列文章,擅长java后端、移动开发、人工智能等,希望大家多多支持。目录一、导读二、概览三、语法规则3.1输入/输出选项3.2保留选项3.3缩小选项3.4优化选项3.5混淆选项3.6预验证选项3.7常规选项四、过滤器4.1增量混淆4.2寻找未使用的代码及方法等(废弃代码)五、混淆基本原则5.1系统相关类不要混淆5.2部分项目相关类不要混淆5.3、添加混淆字典5.4r8&proguard六、推荐阅读一、导读我们继续总结学习基础知识,温故知新。本文讲述AndroidProguard相关知识。二、概览Proguard四部曲:shrink(删减):删减无用代码,包括类、变量、方法和属性,缩减了APK包的大小optimize(优化):优化方法字节码,并移除无用的构造方法obfuscate(混淆):混淆现有代码,将有意义的命名替换为无意义的命名preverify(预校验):给类添加预校验信息,这是J2ME和Java6及以上要求的proguard文档三、语法规则3.1输入/输出选项@filename1“文件名”的缩写‘-includefilename’.-includefilename1从给定文件filename递归读取配置选项-basedirectorydirectoryname1指定这些配置参数或此配置文件中所有后续相对文件名的基目录-injarsclass_path1指定要处理的应用程序的输入jar(或apks、aabs、aars、wars、ears、jmods、zip或目录)。可以使用多个-injars选项指定类路径条目。-outjarsclass_path1指定输出jar的名称(或apks、aabs、aars、wars、ears、jmods、zips或目录)。为了更好的可读性,可以使用多个-outjars选项指定类路径条目。如果没有任何-outjars选项,则不会编写任何jars-libraryjarsclass_path1指定要处理的应用程序的库jar(或apks、aabs、aars、wars、ears、jmods、zips、目录)-skipnonpubliclibraryclasses1指定在读取库jar时跳过非公共类,以加快处理速度并减少ProGuard的内存使用量-dontskipnonpubliclibraryclasses1指定不忽略非公共库类。从版本4.5开始,这是默认设置-dontskipnonpubliclibraryclassmembers1指定不忽略包可见的库类成员(字段和方法)-keepdirectories[directory_filter]1指定要保留在输出jar中的目录(或apks、aabs、aars、wars、ears、jmods、zips或目录)-targetversion1已弃用:此选项仅适用于Java类文件版本 匹配同一选项中第n个匹配的通配符。例如,“com.example.*Foo”匹配“com.example.BarFooBar”。123456789例如,“java/**.class,javax/**.class”匹配和中的所有类java文件javax。此外,文件名前面可以有感叹号“!”'从进一步尝试与后续文件名匹配中排除该文件名。例如,“!**.gif,images/**”匹配images目录中除gif文件之外的所有文件。忽略输入jar中的某些文件,images此配置会删除该目录及其子目录中的所有文件。-injarsin.jar(!images/**)-outjarsout.jar仅保留第一个输入jar中的清单文件:-injarsin1.jar-injarsin2.jar(!META-INF/MANIFEST.MF)-injarsin3.jar(!META-INF/MANIFEST.MF)-outjarsout.jar123456789101112131415161718例如,“foo,*bar”匹配名称foo以及所有以结尾的名称bar。1 匹配任何构造函数。 匹配任何字段。 匹配任何方法。* 匹配任何字段或方法。1234通配符 意义% 匹配任何原始类型("boolean"、"int"等)或"void"类型。? 匹配类名中的任何单个字符。* 匹配类名中不包含包分隔符的任何部分。** 匹配类名的任何部分,可能包含任意数量的包分隔符。*** 匹配任何类型(原始或非原始、数组或非数组)。... 匹配任意数量任意类型的参数。 匹配同一选项中第n个匹配的通配符。123456789请注意?,、和通配符永远不会匹配原始类型。此外,只有通配符才能匹配任何维度的数组类型。例如,“**get*()”匹配“java.lang.ObjectgetObject()”,但不匹配“floatgetFloat()”,也不匹配“java.lang.Object[]getObjects()”。4.1增量混淆-injarsproguardgui.jar-outjarsproguardgui_out.jar-injarsproguard.jar-outjarsproguard_out.jar-libraryjars/jmods/java.base.jmod(!**.jar;!module-info.class)-applymappingproguard.map-keeppublicclassproguard.gui.ProGuardGUI{publicstaticvoidmain(java.lang.String[]);}123456789104.2寻找未使用的代码及方法等(废弃代码)#不进行优化,建议使用此选项,-dontoptimize#指定不混淆输入类文件。默认情况下,ProGuard会混淆代码:它为类和类成员分配新的短随机名称。它删除了仅对调试有用的内部属性,例如源文件名、变量名和行号。-dontobfuscate#不进行预校验,Android不需要,可加快混淆速度。-dontpreverify#指定列出输入类文件的死代码。该列表将打印到标准输出或给定文件。例如,您可以列出应用程序未使用的代码。仅适用于收缩时。-printusage12345678910点击build后,可以看到如下的输出,列出了几个没有使用到的类及方法>Task:app:minifyReleaseWithR8org.fmod.example.CallBackorg.fmod.example.CallBackManagerorg.fmod.example.DeadClassorg.fmod.example.MemoryShakeActivity:publicvoiddpOperate()publicvoidtesta()publicvoidtestb()org.fmod.example.BuildConfigorg.fmod.example.R$colororg.fmod.example.R$drawableorg.fmod.example.R$idorg.fmod.example.R$layoutorg.fmod.example.R$mipmaporg.fmod.example.R$stringorg.fmod.example.R$styleorg.fmod.example.R$xmlorg.fmod.example.Rorg.fmod.example.databinding.ActivityMemoryBinding:publicfinalandroid.widget.ButtonbtMemoryprivatevoid(android.widget.FrameLayout,android.widget.Button)publicstaticorg.fmod.example.databinding.ActivityMemoryBindingbind(android.view.View)publicstaticorg.fmod.example.databinding.ActivityMemoryBindinginflate(android.view.LayoutInflater)publicstaticorg.fmod.example.databinding.ActivityMemoryBindinginflate(android.view.LayoutInflater,android.view.ViewGroup,boolean)androidx.core.location.LocationManagerCompat$InternalSyntheticLambda$1$196e0315f48caa68131c5d4d780ff53e9618a06658f902ea94f753d0df163305$1androidx.core.location.LocationManagerCompat:publicstaticsyntheticjava.lang.Boolean$r8$lambda$JLIcm4BkQpukCiUbhX4BKZUICt4(android.location.LocationManager,androidx.core.location.LocationManagerCompat$GpsStatusTransport)12345678910111213141516171819202122232425262728#不进行优化,建议使用此选项,-dontoptimize#指定不混淆输入类文件。默认情况下,ProGuard会混淆代码:它为类和类成员分配新的短随机名称。它删除了仅对调试有用的内部属性,例如源文件名、变量名和行号。-dontobfuscate#不进行预校验,Android不需要,可加快混淆速度。-dontpreverify#指定列出输入类文件的死代码。该列表将打印到标准输出或给定文件。例如,您可以列出应用程序未使用的代码。仅适用于收缩时。-printusage-keeppublicclassorg.fmod.example.DeadClass{publicstaticvoidmain(java.lang.String[]);}12345678910111213如果我们将某一个未使用的class进行keep,则结果如下>Task:app:minifyReleaseWithR8org.fmod.example.BuildConfigorg.fmod.example.CallBackorg.fmod.example.CallBackManagerorg.fmod.example.DeadClass:publicvoidtesta()publicvoidtestb()publicvoidtestc()org.fmod.example.MemoryShakeActivity:publicvoiddpOperate()publicvoidtesta()publicvoidtestb()org.fmod.example.R$colororg.fmod.example.R$drawableorg.fmod.example.R$idorg.fmod.example.R$layoutorg.fmod.example.R$mipmaporg.fmod.example.R$stringorg.fmod.example.R$styleorg.fmod.example.R$xmlorg.fmod.example.Rorg.fmod.example.databinding.ActivityMemoryBinding:publicfinalandroid.widget.ButtonbtMemoryprivatevoid(android.widget.FrameLayout,android.widget.Button)publicstaticorg.fmod.example.databinding.ActivityMemoryBindingbind(android.view.View)publicstaticorg.fmod.example.databinding.ActivityMemoryBindinginflate(android.view.LayoutInflater)publicstaticorg.fmod.example.databinding.ActivityMemoryBindinginflate(android.view.LayoutInflater,android.view.ViewGroup,boolean)androidx.core.location.LocationManagerCompat$InternalSyntheticLambda$1$196e0315f48caa68131c5d4d780ff53e9618a06658f902ea94f753d0df163305$1androidx.core.location.LocationManagerCompat:publicstaticsyntheticjava.lang.Boolean$r8$lambda$JLIcm4BkQpukCiUbhX4BKZUICt4(android.location.LocationManager,androidx.core.location.LocationManagerCompat$GpsStatusTransport)12345678910111213141516171819202122232425262728293031五、混淆基本原则项目中以下类不应该混淆5.1系统相关类不要混淆四大组件:如Activity、Service、Provider、Broadcast及其Fragment等系统相关类#继承activity,application,service,broadcastReceiver,contentprovider....不进行混淆-keeppublicclass*extendsandroid.app.Activity-keeppublicclass*extendsandroid.app.Application-keeppublicclass*extendsandroid.support.multidex.MultiDexApplication-keeppublicclass*extendsandroid.app.Service-keeppublicclass*extendsandroid.content.BroadcastReceiver-keeppublicclass*extendsandroid.app.backup.BackupAgentHelper-keeppublicclass*extendsandroid.preference.Preference-keeppublicclass*extendsandroid.view.View-keeppublicclass*extendsandroid.support.v4.app.Fragment-keeppublicclass*extendsandroidx.fragment.app.Fragment-keeppublicclass*extendsandroid.content.ContentProvider123456789101112131415view(WebView)相关类-keepclassmembersclass*extendsandroid.app.Activity{publicvoid*(android.view.View);}#不混淆任何一个View中的setXxx()和getXxx()方法,#因为属性动画需要有相应的setter和getter的方法实现-keeppublicclass*extendsandroid.view.View{***get*();voidset*(***);public(android.content.Context);public(android.content.Context,android.util.AttributeSet);public(android.content.Context,android.util.AttributeSet,int);}-keepclasseswithmembersclass*{public(android.content.Context,android.util.AttributeSet);public(android.content.Context,android.util.AttributeSet,int);}12345678910111213141516枚举类#不混淆枚举中的values()和valueOf()方法-keepclassmembersenum*{publicstatic**[]values();publicstatic**valueOf(java.lang.String);}12345注解support下的所有类及其内部类-keepclassandroid.support.**{*;}##保留support下的所有类及其内部类-keeppublicclass*extendsandroid.support.v4.**-keeppublicclass*extendsandroid.support.v7.**-keeppublicclass*extendsandroid.support.annotation.**12345Serializable#继承Serizalizable的类的如下成员不被移除混淆-keepclassmembersclass*implementsjava.io.Serializable{java.lang.ObjectwriteReplace();java.lang.ObjectreadResolve();staticfinallongserialVersionUID;privatestaticfinaljava.io.ObjectStreamField[]serialPersistentFields;privatevoidwriteObject(java.io.ObjectOutputStream);privatevoidreadObject(java.io.ObjectInputStream);}123456789Parcelable的子类和Creator静态成员变量#不混淆Parcelable实现类中的CREATOR字段,-keepclass*implementsandroid.os.Parcelable{publicstaticfinalandroid.os.Parcelable$Creator*;}123455.2部分项目相关类不要混淆数据模型(各种数据模型类,GSON、fastjson等框架解析服务端数据时,混淆后解析不了)-keepclasscom.xxx.entity.**{*;}1Jni接口和java的native方法(这个方法需要和native方法保持一致,混淆后找不到会报错)-keepclasseswithmembernamesclass*{native;}123Java接口(主要针对对外开放的接口)调用反射的地方()抽象内部类比如Animal的内部类不混淆-keepclasscom.xxx.demo.Animal{*;}-keepclasscom.xxx.demo.Animal$*{*;}12使用到的第三方开源库或者引用其他第三方的SDK包#微信支付-keepclasscom.tencent.mm.opensdk.**{*;}12AOP或者读取路径等的地方整理了一个基础混淆文件:Android通用混淆文件5.3、添加混淆字典为了是混淆更混乱,可以添加自定义的混淆字典-classobfuscationdictionaryproguard-dic.txt//类字典-obfuscationdictionaryproguard-dic.txt//混淆字典-packageobfuscationdictionaryproguard-dic.txt//包字典混淆字典下载地址5.4r8&proguard如果不想用R8,想用回ProGuard的话,可以在gradle.properties文件中添加下述配置禁用R8:android.enableR8=falseandroid.enableR8.libraries=false123Android在打包后,一般会有以下几个文件:mapping.txt、usage.txt等mapping.txt→原始与混淆过的类、方法、字段名称间的转换关系;seeds.txt→未进行混淆的类与成员;usage.txt→APK中移除的代码;即废弃代码configuration.txt→missing_rules.txtresources.txt→资源优化记录文件,哪些资源引用了其他资源,哪些资源在使用,哪些资源被移除;12345678910111213141516参考proguard文档六、推荐阅读Java专栏SQL专栏数据结构与算法Android学习专栏未经允许不得转载
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-13 17:35 , Processed in 0.495990 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表