Android 资源混淆 AndResGuard

资源混淆工具库简介


AndResGuard 是一个帮助你缩小 APK 大小的工具,他的原理类似 Java Proguard,但是 只针对资源。他会将原本冗长的资源路径变短,例如将 res/drawable/ activity_advanced_setting_for_test 变为 r/d/a。

AndResGuard 不涉及编译过程,只需输入一个 apk(无论签名与否,debug版,release版均可,在处理过程中会直接将原签名删除),可得到一个实现资源混 淆后的 apk( 若在配置文件中输入签名信息,可自动重签名并对齐,得到可直接发布的 apk )以及对应资源 ID 的 mapping 文件。

底层原理详见 WeMobileDev公众号文章

已知问题:当时在使用7zip压缩的APK时,调用AssetManager#list(String path)返回结果的首个元素为空字符串.   #162
最佳实践
  • 如果不是对 APK size 有极致的需求,请不要把 resource.asrc 添加进 compressFilePattern. (#84  #233)
  • 对于发布于 Google Play 的 APP,建议不要使用 7Zip 压缩,因为这个会导致 Google Play 的优化 Patch 算法失效. (#233)
因为 andresGuard 只混淆资源,所以可以和阿里百川的 Hotfix 完美集成(2.0以前的hotfix只能热修复代码)。

使用

配置 build.gradlle

在 module(app) 中的 build.gradlle 中添加以下代码:
apply plugin: 'com.android.application'
apply plugin: 'AndResGuard' //应用AndResGuard插件

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.13' //添加AndResGuard依赖
    }
}

android {
    signingConfigs { //配置签名信息,注意,要放在buildTypes之前
        release {
            storeFile file("../keystore/bea.keystore") //签名文件位置,【.】代表当前目录,【..】代表父目录
            storePassword "beachinambk"
            keyAlias "bea.keystore"
            keyPassword "beachinambk"
            v2SigningEnabled true
        }

        debug {
            storeFile file("../keystore/debug.keystore")
        }
    }

    buildTypes {
        release { //配置构建选项
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            shrinkResources true
            zipAlignEnabled true
            pseudoLocalesEnabled true
            signingConfig signingConfigs.release //签名文件
        }
    }
}

//-----------------------------配置 AndResGuard-----------------------------
andResGuard {
    mappingFile = null // = file("./resource_mapping.txt") //用于keep住资源的路径的mapping文件所在路径
    use7zip = true    //启用压缩。为true时,useSign必须为true
    useSign = true    // 启用签名。为true时,需要配置signConfig
    keepRoot = false // 为true时,会keep住所有资源的原始路径,只混淆资源的名字
    whiteList = [ //白名单,支持通配符,【+】代表1个或多个,【?】代表0个或1个,【*】代表0个或多个
        "R.mipmap.ic_launcher", "R.drawable.icon",// for your icon
        "R.string.com.crashlytics.*",// for fabric,详见https://docs.fabric.io/android/crashlytics/build-tools.html
        "R.string.google_app_id",// for google-services
        "R.id.*",//任意id
    ]
    compressFilePattern = [ //需要压缩的文件的匹配规则,一般这里不需要动。支持 ? + * 通配符
        "*.png",
        "*.jpg",
        "*.jpeg",
        "*.gif",
        "resources.arsc"
    ]
    sevenzip { //配置7Zip,只需设置 artifact 或 path;支持同时设置,但此时以 path 的值为优先
        artifact = 'com.tencent.mm:SevenZip:1.2.13' 
        //path = "/usr/local/bin/7za"  //path指本地安装的7za(7zip命令行工具)
    }

    // finalApkBackupPath = "${project.rootDir}/final.apk" //可选,指定生成的apk的保存路径
    // digestalg = "SHA-256" //可选: 指定v1签名时生成jar文件的摘要算法,默认值为“SHA-1”
}
66
66
 
1
apply plugin: 'com.android.application'
2
apply plugin: 'AndResGuard' //应用AndResGuard插件
3
4
buildscript {
5
    repositories {
6
        jcenter()
7
    }
8
    dependencies {
9
        classpath 'com.tencent.mm:AndResGuard-gradle-plugin:1.2.13' //添加AndResGuard依赖
10
    }
11
}
12
13
android {
14
    signingConfigs { //配置签名信息,注意,要放在buildTypes之前
15
        release {
16
            storeFile file("../keystore/bea.keystore") //签名文件位置,【.】代表当前目录,【..】代表父目录
17
            storePassword "beachinambk"
18
            keyAlias "bea.keystore"
19
            keyPassword "beachinambk"
20
            v2SigningEnabled true
21
        }
22
23
        debug {
24
            storeFile file("../keystore/debug.keystore")
25
        }
26
    }
27
28
    buildTypes {
29
        release { //配置构建选项
30
            minifyEnabled true
31
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
32
            shrinkResources true
33
            zipAlignEnabled true
34
            pseudoLocalesEnabled true
35
            signingConfig signingConfigs.release //签名文件
36
        }
37
    }
38
}
39
40
//-----------------------------配置 AndResGuard-----------------------------
41
andResGuard {
42
    mappingFile = null // = file("./resource_mapping.txt") //用于keep住资源的路径的mapping文件所在路径
43
    use7zip = true    //启用压缩。为true时,useSign必须为true
44
    useSign = true    // 启用签名。为true时,需要配置signConfig
45
    keepRoot = false // 为true时,会keep住所有资源的原始路径,只混淆资源的名字
46
    whiteList = [ //白名单,支持通配符,【+】代表1个或多个,【?】代表0个或1个,【*】代表0个或多个
47
        "R.mipmap.ic_launcher", "R.drawable.icon",// for your icon
48
        "R.string.com.crashlytics.*",// for fabric,详见https://docs.fabric.io/android/crashlytics/build-tools.html
49
        "R.string.google_app_id",// for google-services
50
        "R.id.*",//任意id
51
    ]
52
    compressFilePattern = [ //需要压缩的文件的匹配规则,一般这里不需要动。支持 ? + * 通配符
53
        "*.png",
54
        "*.jpg",
55
        "*.jpeg",
56
        "*.gif",
57
        "resources.arsc"
58
    ]
59
    sevenzip { //配置7Zip,只需设置 artifact 或 path;支持同时设置,但此时以 path 的值为优先
60
        artifact = 'com.tencent.mm:SevenZip:1.2.13' 
61
        //path = "/usr/local/bin/7za"  //path指本地安装的7za(7zip命令行工具)
62
    }
63
64
    // finalApkBackupPath = "${project.rootDir}/final.apk" //可选,指定生成的apk的保存路径
65
    // digestalg = "SHA-256" //可选: 指定v1签名时生成jar文件的摘要算法,默认值为“SHA-1”
66
}

配置 whiteList 与 mappingFile

默认 andResGuard 会混淆所有资源文件,而白名单则允许我们指定不被混淆的资源文件。
例如友盟、融云在 sdk 里面写死了资源名,所以如果被我们混淆之后就找不到指定资源,则运行时就会崩溃。
另外,所有使用 getIdentifier 访问的资源也都需要加入白名单。
getResources().getIdentifier(“com.test.demo:drawable/icon”,null,null);//包名 : 资源文件夹名 / 资源名
getResources().getIdentifier(“icon”, “drawable”, “com.test.demo”);//ID名,资源属性,包名
2
2
 
1
getResources().getIdentifier(“com.test.demo:drawable/icon”,null,null);//包名 : 资源文件夹名 / 资源名
2
getResources().getIdentifier(“icon”, “drawable”, “com.test.demo”);//ID名,资源属性,包名
可以在 white_list.md 查看更多第三方 sdk 的白名单配置。

白名单机制只作用于资源的 specsName,不会 keep 住资源的路径。如果想 keep 住资源的路径,可以使用 mappingFile。
例如我想 keep 住所有 folder 中的  icon,可以在 mappingFile 指向的文件添加:
res path mapping:
    res/mipmap-hdpi-v4 -> res/mipmap-hdpi-v4
    res/mipmap-mdpi-v4 -> res/mipmap-mdpi-v4
    res/mipmap-xhdpi-v4 -> res/mipmap-xhdpi-v4
    res/mipmap-xxhdpi-v4 -> res/mipmap-xxhdpi-v4
    res/mipmap-xxxhdpi-v4 -> res/mipmap-xxxhdpi-v4
6
6
 
1
res path mapping:
2
    res/mipmap-hdpi-v4 -> res/mipmap-hdpi-v4
3
    res/mipmap-mdpi-v4 -> res/mipmap-mdpi-v4
4
    res/mipmap-xhdpi-v4 -> res/mipmap-xhdpi-v4
5
    res/mipmap-xxhdpi-v4 -> res/mipmap-xxhdpi-v4
6
    res/mipmap-xxxhdpi-v4 -> res/mipmap-xxxhdpi-v4

启动任务

使用 Android Studio 的同学可以在 andresguard 下找到相关的构建任务,命令行可直接运行./gradlew resguard[BuildType | Flavor],如:
gradlew.bat resguardRelsese    //Windows
./gradlew reguardRelease    //OS X or Linux
2
2
 
1
gradlew.bat resguardRelsese    //Windows
2
./gradlew reguardRelease    //OS X or Linux
这里的任务命令规则和 build 中的 assemble 一致。
双击或右键 Run... 下图中的选中任务,构建以及混淆就会开始:

完成后会提示你混淆后的 apk 生成目录:
Backup Final APk(V2) to ***\Test\app\build\outputs\apk\release\app-release.apk
<--AndResGuard Done! You can find the output in ***\Test\app\build\outputs\apk\release\AndResGuard_app-release
2
2
 
1
Backup Final APk(V2) to ***\Test\app\build\outputs\apk\release\app-release.apk
2
<--AndResGuard Done! You can find the output in ***\Test\app\build\outputs\apk\release\AndResGuard_app-release

如果不设置 finalApkBackupPath 则会如上面一样默认覆盖 assemble 输出的apk,如果配置则输出至 finalApkBackupPath 配置的路径。
例如配置为【finalApkBackupPath = "${project.rootDir}/final.apk"】后的 输出为
Backup Final APk(V2) to ***\Test\final.apk
<--AndResGuard Done! You can find the output in ***\Test\app\build\outputs\apk\release\AndResGuard_app-release
2
2
 
1
Backup Final APk(V2) to ***\Test\final.apk
2
<--AndResGuard Done! You can find the output in ***\Test\app\build\outputs\apk\release\AndResGuard_app-release

生成的文件

默认会生成4种apk,我们选择签名、压缩、对齐后的 apk 即可,后缀名是*_7zip_aligned_signed.apk

混淆前 apk 解压后的资源文件:
混淆后 apk 解压后的资源文件:
2018-7-11

猜你喜欢

转载自www.cnblogs.com/baiqiantao/p/9292266.html