Android代码混淆配置:ProGuard的重要性

访客 359 0

前言
对于一个应用的发布包来说,混淆效果是很正常的。通过添加混淆,可以使用无意义的命名重新命名类、方法和变量,使得应用代码难以被反编译和逆向工程,并且在一定程度上减小包的大小。

在Android中,我们通常使用的集成开发环境是Android Studio,它内置了ProGuard混淆工具。因此,我们最常用且最简单的混淆方式就是使用ProGuard进行代码混淆。ProGuard主要提供了四个功能:

  1. 压缩(Shrink):用于检测和删除没有使用的类、字段、方法和属性。
  2. 优化(Optimize):对于字节码进行优化,并且移除无用指令。
  3. 混淆(Obfuscate):使用a,b,c等名称对类,字段和方法进行重命名。
  4. 预检(Preverify):主要是在Java平台上对处理后的代码进行预检。

在Android Studio中,已经集成了ProGuard。因此,默认情况下,项目中已经配置了proguard-rules.pro文件。我们可以直接对该文件进行修改。

Android Studio使用ProGuard主要包括如下几个步骤:

  1. 配置文件中打开混淆。
  2. 配置混淆文件。
  3. 检查日志文件,apk文件以及apk运行状况,查询是否有错误出现。
    一. 配置文件中打开混淆
    在build.gradle文件中配置如下代码:
```
android {
    buildTypes {
        debug {
            ...
        }
        release {
            //混淆开关
            minifyEnabled true
            // 是否zip对齐
            zipAlignEnabled true
            // 移除无用的resource文件
            shrinkResources false
           // 是否打开debuggable属性,用于调试时使用,发布版本建议关闭该属性以提高安全性和性能。
           debuggable false 
        }
    }
}
``` 

混淆一般是配置在release包中,原因是因为debug包一般来说是开发者在开发需要时运行调试的,混淆会减慢打包速度,对于开发程序效率有所影响。但是这不表示我们在开发程序时不注重混淆设置,在混淆设置不正确的情况下可能会发生查找不到某个类的异常,因此如果项目中有打开混淆,在需求完成后添加混淆并自测是必要步骤。

二. 配置混淆文件
在Android Studio中,默认的ProGuard配置文件是proguard-rules.pro。因此,我们只需对该文件进行配置即可。

尽管ProGuard配置相对复杂,但其核心内容主要涵盖以下几个方面:

以下是对原文的改写: 基本配置包括混淆算法、压缩等级以及混淆的范围等。需要注意的是,某些项需要保持不被混淆,应进行警告处理。ProGuard文件的语法相当复杂,具体内容可以参考ProGuard官方文档。本文将不再详述,仅举例说明常见的apk混淆文件配置。

我们通常会在ProGuard文件中看到以下几个部分:

  1. 基本配置,设定混淆的规则等,基本配置是每个混淆文件必须存在的,并且此块内容大部分通用,可以直接copy。

  2. 基本的keep项,多数Android工程都需要非混淆的内容,包括有四大组件等内容,此项内容也大部分通用,也可以直接copy。

  3. 为了混淆三方引入的lib包,您需要访问各自官网查找相应的混淆添加代码。

  4. 其他需要澄清的内容包括:实体类、JSON解析类、WebView和JavaScript调用模块,以及与反射相关的类和方法。接下来,我们将分别给出这些内容的示例说明。

  5. 基本配置在大多数情况下保持稳定,一般的项目可以直接复制使用。以下是一个示例:

# 指定压缩级别-optimizationpasses 5
# 不跳过非公共的库的类成员-dontskipnonpubliclibraryclassmembers
# 混淆时采用的算法-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# 把混淆类中的方法名也混淆了-useuniqueclassmembernames
# 指定不去忽略非公共的库的类-dontskipnonpubliclibraryclasses
# 不做预检验,preverify是proguard的四大步骤之一,可以加快混淆速度-dontpreverify
# 忽略警告(?)-ignorewarnings
# 混淆时不使用大小写混合,混淆后的类名为小写(大小写混淆容易导致class文件相互覆盖)-dontusemixedcaseclassnames
# 优化时允许访问并修改有修饰符的类和类的成员-allowaccessmodification
# 将文件来源重命名为“SourceFile”字符串-renamesourcefileattribute SourceFile 
保留行号-keepattributes SourceFile,LineNumberTable 
保持泛型-keepattributes Signature 
保持注解-keepattributes *Annotation*,InnerClasses 
保持测试相关代码-dontnote junit.framework.** -dontnote junit.runner.** -dontwarn android.test.** -dontwarn android.support.test.** -dontwarn org.junit.**

基本项目配置:
多数是包括序列化、Android四大组件等基本内容的混淆keep,对于常规的项目而言区别不大,也可以进行复制。示例如下:
# Parcelable-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *;}
# Serializable-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
    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();
}
# 保留R下面的资源-keep class **.R$* {*;}
# 保留四大组件,自定义的Application,Fragment等这些类不被混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Fragment 
以下是改写后的文案:

```
# androidx混淆规则
-keep class com.google.android.material.** {*;}
-keep class androidx.** {*;}
-keep public class * extends androidx.**
-keep interface androidx.** {*;}
-dontwarn com.google.android.material.**
-dontnote com.google.android.material.**
-dontwarn androidx.**
-printconfiguration
-keep,allowobfuscation @interface androidx.annotation.Keep
-keep @androidx.annotation.Keep class *
-keepclassmembers class * {
    @androidx.annotation.Keep *;
}

# 三方SDK的混淆
请根据各自的SDK官网上提供的文档进行相应的配置,以下仅以OKHTTP和Gson作为示例。
``` 
# 设置WebView的混淆规则,避免警告信息
-dontwarn android.webkit.WebView
-dontwarn android.net.http.SslError
-keep public class android.webkit.WebView
-keep public class android.net.http.SslError
-keep public class android.webkit.WebViewClient

# 其他内容可以按照下面的格式进行粗暴的设置保留效果: 
以下是改写后的段落:

```
-keep class com.example.package.** { *; }

5. Log过滤
在混淆文件中,还可以配置Log过滤效果。示例代码如下:
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
}

三. 混淆结果
在添加混淆之后,我们可以记录和打印混淆和未混淆的类名,在排查时非常有用。通过在混淆文件中添加以下代码,可以查看被编译的类及其文件结构:
``` 

混淆映射,生成映射文件

在生成release包时,添加以下代码会同时生成三个日志文件:-verbose,-printmapping proguardMapping.txt(输出apk包内所有的class的内部结构),-dump dump.txt(未混淆的类和成员),-printseeds seeds.txt(列出从apk中删除的代码),-printusage unused.txt。我们可以使用上述三个文件作为参考,在排查混淆问题时能够快速进行排查。

完成上述任务后,务必对当前项目进行全面测试,以确保添加的keep选项是否完整。为此,需要仔细检查所有项目内容和类别,以确保没有任何问题存在才能提交。

自从Android Gradle插件升级至3.4.0版本后,Proguard和R8带来了一个新特性-全新一代的混淆工具R8。作为D8的混淆工具升级替代方案,R8在应用压缩和优化方面提供了更出色的体验和效果优化。

自Gradle插件3.4.0版本开始,R8已默认启用。R8将脱糖、压缩、混淆、优化和dex处理整合到一个步骤中,相较于Proguard而言,构建性能有一定程度的提升。

需要注意的是,尽管R8可以与现有的ProGuard规则配合使用,因此我们升级到R8时无需进行修改。然而,由于R8具有特殊的压缩和优化功能,不能排除移除了ProGuard中代码的可能性。因此,在升级后仍需要进行全面的工程测试。

如果使用R8时遇到问题,需要停用R8,请在gradle.properties文件中添加以下内容:

改写后的文案如下:

```
在本文中,我们主要讨论了常规的proguard混淆以及相应文件配置。由于每个项目中的代码都各不相同,因此混淆文件的添加内容并不能一概而论。除了公共部分之外,大多数配置都有所不同,需要根据实际情况灵活添加。
```

标签: 文件 代码 内容 项目

发表评论 (已有0条评论)

还木有评论哦,快来抢沙发吧~