相关文章推荐
爱喝酒的香槟  ·  《九阴白骨爪》今日腾讯视频公映 ...·  1 年前    · 
安静的棒棒糖  ·  kaggle手机验证不了的解决方案_kagg ...·  1 年前    · 
帅气的匕首  ·  今年,合肥将开通3条地铁延长线!·  2 年前    · 
性感的桔子  ·  顺圣太后_百度百科·  3 年前    · 
严肃的熊猫  ·  坡坡文_抖抖音·  3 年前    · 
Code  ›  Android 混淆打包开发者社区
webview 社区功能 android框架 代码混淆
https://cloud.tencent.com/developer/article/1560065
发财的小马驹
2 年前
作者头像
Yif
0 篇文章

Android 混淆打包

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > Android 进阶 > Android 混淆打包

Android 混淆打包

作者头像
Yif
发布 于 2019-12-26 15:03:48
992 0
发布 于 2019-12-26 15:03:48
举报
undefined
undefined

代码混淆

代码混淆原因

Java 是一种跨平台的、解释型语言, Java 源代码编译成中间”字节码”存储于 class 文件中。

由于跨平台的需要,Java 字节码中包括了很多源代码信息,如变量名、方法名,并且通过这些名称来访问变量和方法,这些符号带有许多语义信息,很容易被反编译成 Java 源代码。为了防止这种现象,我们可以使用 Java 混淆器对 Java 字节码进行混淆。 混淆就是对发布出去的程序进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能,而混淆后的代码很难被反编译,即使反编译成功也很难得出程序的真正语义。被混淆过的程序代码,仍然遵照原来的档案格式和指令集,执行结果也与混淆前一样,只是混淆器将代码中的所有变量、函数、类的名称变为简短的英文字母代号,在缺乏相应的函数名和程序注释的况下,即使被反编译,也将难以阅读。同时混淆是不可逆的,在混淆的过程中一些不影响正常运行的信息将永久丢失,这些信息的丢失使程序变得更加难以理解。

Proguard 作用:

  • 压缩 shrinks :检查并移除代码中无用的类,字段,方法,属性。
  • 优化 optimizes :对字节码进行优化,移除无用的指令。
  • 混淆 obfuscates :使用a,b,c,d等简短而无意义的名称,对类,字段和方法进行重名,这样即使代码被逆向工程,对方也比较难以读懂。
  • 预检测 Preveirfy :在java平台上对处理后的代码进行再次检测。

Keep 关键字

有时候你是不是还想着,我不需要保持类名,我只需要把该类下的特定方法保持不被混淆就好,那你就不能用 keep 方法了, keep 方法会保持类名,而需要用 keepclassmembers ,如此类名就不会被保持,为了便于对这些规则进行理解,官网给出了以下表格:

保留

防止被移除或者被重命名

防止被重命名

类和类成员

-keep

-keepnames

仅类成员

-keepclassmembers

-keepclassmembernames

如果拥有某成员,保留类和类成员

-keepclasseswithmembers

-keepclasseswithmembernames

keep:

  • keep :包留类和类中的成员,防止他们被混淆
  • keepnames :保留类和类中的成员防止被混淆,但成员如果没有被引用将被删除
  • keepclassmembers :只保留类中的成员,防止被混淆和移除。
  • keepclassmembernames :只保留类中的成员,但如果成员没有被引用将被删除。
  • keepclasseswithmembers :如果当前类中包含指定的方法,则保留类和类成员,否则将被混淆。
  • keepclasseswithmembernames :如果当前类中包含指定的方法,则保留类和类成员,如果类成员没有被引用,则会被移除。

混淆原则

  • jni 方法不可混淆,因为需要与 native 方法保持一致;
  • 反射用到的类不混淆(否则反射可能出现问题);
  • AndroidMainfest 中的类不混淆,四大组件和 Application 的子类和 Framework 层下所有的类默认不会进行混淆;
  • Parcelable 的子类和 Creato r静态成员变量不混淆,否则会产生 Android.os.BadParcelableException 异常;
  • 使用 GSON、fastjson 等框架时,所写的 JSON 对象类不混淆,否则无法将 JSON 解析成对应的对象;
  • 使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则;
  • 有用到 WEBView 的JS调用也需要保证写的接口方法不混淆;
  • 使用 enum 类型时需要注意避免以下两个方法混淆,因为 enum 类的特殊性,以下两个方法会被反射调用 -keepclassmembers enum * {   public static **[] values();   public static ** valueOf(java.lang.String);   }

第三方库的混淆原则

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

基本配置

-optimizationpasses 5  #指定代码的压缩级别 0 - 7,一般都是5,无需改变
-dontusemixedcaseclassnames #不使用大小写混合,混淆后类名称为小写
#告诉Proguard 不要跳过对非公开类的处理,默认是跳过
-dontskipnonpubliclibraryclasses #如果应用程序引入的有jar包,并且混淆jar包里面的class
#不做预校验,preverify是proguard的4个功能之一
#android不需要preverify,去掉这一步加快混淆速度
-dontpreverify
-verbose #混淆时记录日志(混淆后生产映射文件 map 类名 -> 转化后类名的映射
-printmapping proguardMapping.txt #指定映射文件的名称
#指定混淆时的算法,后面的参数是一个过滤器
#这个过滤器是谷歌推荐的算法,一般也不会改变
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#类型转换错误 添加如下代码以便过滤泛型(不写可能会出现类型转换错误,一般情况把这个加上就是了),即避免泛型被混淆
-keepattributes Signature
#假如项目中有用到注解,应加入这行配置,对JSON实体映射也很重要,eg:fastjson
-keepattributes *Annotation*
#抛出异常时保留代码行数
-keepattributes SourceFile,LineNumberTable

比较完整的配置

-optimizationpasses 5  #指定代码的压缩级别 0 - 7,一般都是5,无需改变
-dontusemixedcaseclassnames #不使用大小写混合
#告诉Proguard 不要跳过对非公开类的处理,默认是跳过
-dontskipnonpubliclibraryclasses #如果应用程序引入的有jar包,并且混淆jar包里面的class
-verbose #混淆时记录日志(混淆后生产映射文件 map 类名 -> 转化后类名的映射
#指定混淆时的算法,后面的参数是一个过滤器
#这个过滤器是谷歌推荐的算法,一般也不会改变
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
#类型转换错误 添加如下代码以便过滤泛型(不写可能会出现类型转换错误,一般情况把这个加上就是了),即避免泛型被混淆
-keepattributes Signature
#假如项目中有用到注解,应加入这行配置,对JSON实体映射也很重要,eg:fastjson
-keepattributes *Annotation*
#抛出异常时保留代码行数
-keepattributes SourceFile,LineNumberTable
#保持 native 的方法不去混淆
-keepclasseswithmembernames class * {
    native <methods>;
#第三方开源框架以及第三方jar包中的代码不是我们的目标和关心的对象,因此我们全部忽略不进行混淆。
#EventBus的代码没必要混合
-keep class com.XXX.eventbus.** { *; }
-keep class com.XXX.event.** { *; }
-keep class com.XXX.eventbus.util.** { *; }
-keep class android.os.**{*;}
-keepclassmembers class ** {
    public void onEvent*(**);
#litepal 数据库框架
-dontwarn org.litepal.*
-keep class org.litepal.** { *; }
-keep enum org.litepal.**
-keep interface org.litepal.** { *; }
-keep public class * extends org.litepal.**
-keepclassmembers class * extends org.litepal.crud.DataSupport{*;}
#v4包下的文件都不要混淆 -dontwarn   如果有警告也不终止
-dontwarn android.support.v4.**
-keep class android.support.v4.app.**{*;}
-keep class android.support.v4.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment  #所有fragment的子类不要去混淆
-keep public class * extends android.app.Activity  #所有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
#保持指定规则的方法不被混淆(Android layout 布局文件中为控件配置的onClick方法不能混淆)
-keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
#保持自定义控件指定规则的方法不被混淆
-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
#保持枚举 enum 不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
#保持 Parcelable 不被混淆(aidl文件不能去混淆)
-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
#需要序列化和反序列化的类不能被混淆(注:Java反射用到的类也不能被混淆)
-keepnames class * implements java.io.Serializable
#保护实现接口Serializable的类中,指定规则的类成员不被混淆
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
#保持R文件不被混淆,否则,你的反射是获取不到资源id的
-keep class **.R$* { *; }
#以下针对App本身设置
#保护WebView对HTML页面的API不被混淆
-keep class **.Webview2JsInterface { *; }
#如果你的项目中用到了webview的复杂操作,最好加入
-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.WebChromeClient {
  public void *(android.webkit.WebView,java.lang.String);
#转换JSON的JavaBean,类成员名称保护,使其不被混淆
-keepclassmembernames class com.cgv.cn.movie.common.bean.** { *; }
#保证自定义类不被混淆 XXX换成你自己的包名
-keep class com.XXX.view.** {*;}
# 保持实体数据结构接口不被混淆(也就是被GSON注解的实体结构)此处是自己接口的包名 XXX换成你自己的包名
-keep class com.XXX.model.** { *; }
#使用gson包解析数据时,出现 missing type parameter 异常,添加如下代码
-dontobfuscate #不混淆输入的类文件
-dontoptimize  #不优化输入的类文件
# 不混淆 GSON
-keep class com.google.gson.** { *; }
-keep class com.google.gson.JsonObject {*;}
 
推荐文章
爱喝酒的香槟  ·  《九阴白骨爪》今日腾讯视频公映 严屹宽阮巨演绎东邪师徒恋_梅超风
1 年前
安静的棒棒糖  ·  kaggle手机验证不了的解决方案_kaggle无法绑定手机号-CSDN博客
1 年前
帅气的匕首  ·  今年,合肥将开通3条地铁延长线!
2 年前
性感的桔子  ·  顺圣太后_百度百科
3 年前
严肃的熊猫  ·  坡坡文_抖抖音
3 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号