【问题标题】:What is the good strategy when dealing with Proguard, MultiDex, Testing and Product Flavors?在处理 Proguard、MultiDex、测试和产品风味时,什么是好的策略?
【发布时间】:2016-08-05 16:39:53
【问题描述】:

我有一个引用 ~ 100K 方法的应用,其中 min Sdk = 16

这里有两种组装方式:

  • Proguard 将这组方法缩减到只有 44K 个方法
  • 使用多敏捷

现在我有一些常见的用例:

  1. 在模拟器和设备上运行和调试
    • 要求尽可能快
  2. 进行测试(集成和 UI)
    • 它需要运行(我在使用 MultiDex 运行 Espresso 时遇到了一些问题)
  3. 制作 Prod APK
    • 它要求尽可能可靠和缩小

你们对组装策略有什么建议吗?

3/ 产品

  • 使用 Proguard 减小 APK 大小
  • 使用 Proguard 进行混淆
  • 尽量不要使用 Multidex(可能会失败)

2/ 测试

  • 使用 minSdkVersion 21(我读到从 21 开始启用 pre-dexing,这样可以节省时间)
  • ???

1/ 调试

  • 使用 minSdkVersion 21(我读到从 21 开始启用 pre-dexing,这样可以节省时间)
  • ???

这是 Gradle 文件:

    productFlavors {
        dev {
            minSdkVersion 21
            multiDexEnabled ???
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        prod {
            // The actual minSdkVersion for the application.
            minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION
            multiDexEnabled false
        }
    }
    defaultConfig {
        applicationId "xxxx"
        targetSdkVersion ANDROID_BUILD_TARGET_SDK_VERSION
        minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION
        versionCode ANDROID_BUILD_VERSION_CODE
        versionName ANDROID_BUILD_APP_VERSION_NAME
    }

    buildTypes {
        release {
            debuggable false
            ext.enableCrashlytics = true
            renderscriptOptimLevel 3
            signingConfig android.signingConfigs.release
            zipAlignEnabled true
            minifyEnabled true
            //  shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        debug {
            debuggable true
            renderscriptOptimLevel 3
            applicationIdSuffix ".debug"
            versionNameSuffix "debug"
            minifyEnabled false
        }
    }

【问题讨论】:

    标签: android gradle proguard android-productflavors android-multidex


    【解决方案1】:

    根据@Muzikant 的提议,我主要同意,我总结了我今天的愿景

    • 如果可以,尽量不要使用MultiDex
      • 可能会碰巧达到 65K 的数量,方法是测试库带来的开销(所以使用 MutliDex)
      • MultiDex 可能会比 Proguard 进程更快(待检查),因此调试可能会很有趣
    • 尝试使用与发布 APK 最接近的 APK 进行测试

    我的建议是:

    1. 因为有 3 个构建案例,所以只需要 3 个构建类型:

      • 发布
      • 调试
      • 验证(test是保留字)
    2. 使用两种口味:

      • 与您的应用程序的minSdkVersion 一起发布
      • 还有一款用于开发,使用更新的 minSdkVersion(构建速度更快,测试功能更多,espresso 更易于使用...)
    3. 不要混淆调试

    4. 为了在测试阶段使用 Proguard,Gradle DSL 的特定关键字是必要的testProguardFile('proguard-rules-test.pro')

    5. 使用testBuildType = "validation"指出将用于调试的构建

    6. 对测试进行混淆处理(至少对于您的 CI 系统上的 UI 系统和功能测试)

    7. 仅对发布getDefaultProguardFile('proguard-android-optimize.txt')使用优化Proguard规则,测试和调试仅使用getDefaultProguardFile('proguard-android.txt')

    我的 Proguard 文件的架构如下:

    1. release proguard-rules-release.pro 的一个主文件,其中包括一组专用的 Proguard 文件,-include proguard-rules-fabric.pro

    2. debug proguard-rules-debug.pro 的一秒文件,其中包括 proguard-rules-release.pro

    3. 三分之一文件用于调试 proguard-rules-dontobfuscate.pro 禁用混淆

    4. 用于测试 proguard-rules-test.pro 的第四个文件,其中包括proguard-rules-debug.pro 和测试所需的规则

    这是 Gradle 文件:

    android {
        ...
        compileSdkVersion ANDROID_BUILD_SDK_VERSION
        buildToolsVersion ANDROID_BUILD_TOOLS_VERSION
    
        productFlavors {
            // Define separate dev and prod product flavors.
            dev {
                // dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
                // to pre-dex each module and produce an APK that can be tested on
                // Android Lollipop without time consuming dex merging processes.
                minSdkVersion 21
                multiDexEnabled false
    
            }
            prod {
                // The actual minSdkVersion for the application.
                minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION
                multiDexEnabled false
            }
        }
        defaultConfig {
            applicationId "x.y.app.z"
            targetSdkVersion ANDROID_BUILD_TARGET_SDK_VERSION
            minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION
            versionCode ANDROID_BUILD_VERSION_CODE
            versionName ANDROID_BUILD_APP_VERSION_NAME
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        // point thge build for testing
        testBuildType = "validation"
    
        buildTypes {
            release {
                debuggable false
                ext.enableCrashlytics = true
                renderscriptOptimLevel 3
                signingConfig android.signingConfigs.release
                zipAlignEnabled true
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-release.pro'
            }
            debug {
                debuggable true
                renderscriptOptimLevel 3
                applicationIdSuffix ".debug"
                versionNameSuffix "debug"
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro', `proguard-rules-dontobfuscate.pro`
            }
    
            validation.initWith(debug)
            validation {
                signingConfig android.signingConfigs.release
                debuggable false
                renderscriptOptimLevel 3
                applicationIdSuffix ".test"
                versionNameSuffix "test"
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro'
                testProguardFile('proguard-rules-test.pro')
            }
        }
    ...
    }
    

    我还有一些未解决的问题:

    • 如何使用 Android Studio 的自动调试签名进行验证构建? (但我不确定影响)

    • 我仍然需要在验证 BuildType 中添加 proguardFiles 属性,而我的 testProguardFile('proguard-rules-test.pro') 包含调试!

    【讨论】:

    • 可能为第一个打开点添加validation.initWith(buildTypes.debug)(待检查)
    • 我明白了这一点“仅将优化 Proguard 规则用于发布 getDefaultProguardFile('proguard-android-optimize.txt'),用于测试和调试只需使用 getDefaultProguardFile('proguard-android.txt') “ 给出。为什么我们不使用优化代码运行测试?我已经对我的代码进行了混淆测试,但我遇到了优化代码的问题。
    【解决方案2】:

    为了避免多重索引,我在调试和发布版本上都使用了 proguard。

    我的build.gradle 文件如下所示:

    debug {
        minifyEnabled true
        proguardFiles 'proguard_debug.pro'
        signingConfig signingConfigs.debug
        debuggable true
    }
    release {
        minifyEnabled true
        proguardFiles 'proguard_release.pro'
        signingConfig signingConfigs.release
        debuggable false
    }
    

    为了尽量减少调试和发布之间的差异,并允许正确调试调试版本,proguard_debug.pro 文件包含以下 proguard 说明:

    -include proguard_release.pro
    
    -dontobfuscate
    -dontoptimize
    -keep class my.package.name.** {*; }
    

    这样,我只维护一个 proguard 配置(在 proguard_release.pro 中),调试版本是使用相同的配置构建的,但不会混淆代码。

    该配置解决了所有提到的问题:

    1. 不需要多索引(所以是否与 API 一起使用没有两难选择) 21+,你可以使用 Espresso)
    2. 调试版本和发布版本相同,只是调试版本不会混淆您的代码

    【讨论】:

    • 好的,很好。请注意,它也可能存在由混淆引起的问题!然而,构建 apk 对于调试和测试来说真的很慢。你能适应这种延迟吗?
    • 考虑到替代方案,这对我来说是最好的解决方案。混淆不是问题,因为调试 proguard 配置具有 -dontobfuscate 标志
    • 是的,我只是说混淆可能会给应用程序带来错误。这也很好测试
    • 当代码被混淆和优化时,是否可以使用对象注入运行检测测试用例?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    • 1970-01-01
    • 2021-07-29
    • 2012-07-27
    • 2015-07-09
    • 1970-01-01
    • 2013-08-27
    相关资源
    最近更新 更多