处理Proguard,MultiDex,测试和产品口味时,有什么好的策略?

时间:2016-04-14 08:37:39

标签: android gradle proguard android-productflavors multidex

我有一个引用~100K方法的应用程序,最小Sdk = 16

这是两个组装选项:

  • Proguard将这一系列方法缩减为仅44K方法
  • 使用Multi Dex

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

  1. 在模拟器和设备上运行和调试
    • 需要尽可能快
  2. 做测试(集成和用户界面)
    • 需要运行(我在使用MultiDex运行Espresso时遇到问题)
  3. 制作Prod APK
    • 它需要尽可能可靠和缩小
  4. 你们有没有关于组装策略的建议?

    3 / Prod

    • 使用Proguard降低APK尺寸
    • 使用Proguard进行模糊处理
    • 尽量不要使用Multidex(可能会失败)

    2 /测试

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

    1 / Debug

    • 使用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
            }
        }
    

2 个答案:

答案 0 :(得分:2)

Based on the proposal of @Muzikant, that I mainly agree, I summarized my today vision

  • Try not using MultiDex if you can.
    • It may happen to reach the 65K number with the overhead of method brings with test libraries (so use MutliDex)
    • It may happen that MultiDex is faster than Proguard process (to be checked), so it could be interesting for debugging
  • Try to use an APK for testing that is the closest to the release APK

My recommendations are:

  1. as there are 3 builds cases, just make 3 buildTypes :

    • release
    • debug
    • validation (test is a reserved word)
  2. use 2 flavors:

    • one for release with the minSdkVersion of your app
    • and one for development that uses a more up-to-date minSdkVersion (faster building, more features for testing, easier to use espresso...)
  3. do not obfuscate for debugging

  4. for using Proguard during the test phase, a specific keyword of the Gradle DSL is necessary testProguardFile('proguard-rules-test.pro')

  5. point the build that will be used for debugging with testBuildType = "validation"

  6. do obfuscate for testing (at least for UI system and functional tests on your CI system)

  7. use the optimisation Proguard rules only for release getDefaultProguardFile('proguard-android-optimize.txt'), for testing and debug just use getDefaultProguardFile('proguard-android.txt')

The architecture of my Proguard files is the following:

  1. one main file for release proguard-rules-release.pro that include a set of dedicated Proguard files with -include proguard-rules-fabric.pro

  2. one second file for debug proguard-rules-debug.pro that include proguard-rules-release.pro

  3. one third file for debug proguard-rules-dontobfuscate.pro that disable obfuscation

  4. one forth file for testing proguard-rules-test.pro that include proguard-rules-debug.pro and the rules necessary for testing

Here is the Gradle file:

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')
        }
    }
...
}

I still have some open points to solve :

  • How to use the automatic debug signing of Android Studio for the validation build ? (but I'm not sure about the impact)

  • I still have to add proguardFiles attribute in the validation BuildType while I have the testProguardFile('proguard-rules-test.pro') that include the debug !

答案 1 :(得分:1)

我在调试版和发行版上都使用了proguard,以避免使用multidex。

我的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. 调试和发布版本是相同的,除了调试版本不会混淆您的代码