Built-in Shrinkerを使ってデバッグビルドで64k問題を回避する


※ Built-in Shrinkerは、Android Gradle Plugin 3.3からR8に置き換わりました。

Androidには64k問題という開発者にとって非常につらい問題があります。
こやつはそれ自体よりも、multidex化によるビルド時間の増加によって引き起こされる開発イテレーションの低下のほうが問題になります。

proguardによる回避

proguardのshrink工程において、参照していないメソッドが削除され、これによって64k問題の回避が可能になります。

proguardの問題

proguardに難読化処理も含まれているため、debugビルドでかけるとデバッグ効率が悪くなります。
そのため、通常はreleaseビルドでない限りproguardをかけないのが一般的かと思います。

しかし、proguardをかけないということは前述のshrinkが行われないため、releaseビルドでは64kに達していないのにdebugビルドでは64kを超えてしまってい、やむなくmultidex化するということが起こります。

また、proguardはInstant Runに対応していないため、Instant Runを有効にしている場合も問題になります。

Built-in Shrinker

これらの問題を解決するためにgradle-plugin 2.0.0で新たに、Built-in Shrinkerという仕組みが追加されました。
これは、難読化はせず、shrink処理のみを行うdebugビルドにおけるproguardの代替ツールです。

使い方はbuild.gradledebugbuildTypeに以下の設定をするだけです。

build.gradle
android {
    

    buildTypes {
        debug {
            debuggable true
            minifyEnabled true
            useProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

minifyEnabledtrueuseProguardfalseにして、releaseビルド同様にproguardFilesを設定します。

この設定により、debugビルドでもshrinkが有効になり、debugビルドだけ64kに達するということを回避できます。
体感のビルド時間は、「proguardなしよりも遅く、proguardより早い」程度になります。

なお、Built-in Shrinkerはmultidexをサポートしていないのでmultidexの設定は全て消す必要があります。
まあ状態としては排他になるはずなので、既存のmultidex設定を消す手間以外には問題にはなりません。

その他

警告あるぞエラーが出る

(gradle plugin 2.2.1で出なくなった?) 起きました

Error:Execution failed for task ':app:transformClassesWithNewClassShrinkerForDebug'.
> Warnings found during shrinking, please use -dontwarn or -ignorewarnings to suppress them.

ビルドすると、こんなエラーが出ることがあります。

以下の定義のファイルを用意して、

shrinker-rules.pro
-ignorewarnings

proguardFiles の定義に追加すればOKです。

build.gradle
android {
    

    debug {
        debuggable true
        minifyEnabled true
        useProguard false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro', 'shrinker-rules.pro' // ← 追加
    }
}

Analyze APK

Android Studio 2.2から、Analyze APKという機能が追加されました。
これを使うすることで既存のAPKの解析が行えるのですが、その中にはdexファイル内のメソッド数をカウントしてくれる機能があります。

こちらは
Build - Analyze APK
から利用できるので、こちらも活用してみてください。

KeepSafe/dexcount-gradle-pluginというプラグインを利用していましたが、メソッド数を知るためにわざわざプラグインを入れなくてもよくなったは良いですね。

dexguard

dexguard 7.2.07 時点では、どうやらdexguardプラグインはminifyEnabledのみで有効化し、useProguardの値を見てくれないみたいで、shrinkerを有効にする方法がわかりませんでした。

そもそもメソッド数を増やさないためには

Jake神の教えに従おう
Exploring Java's Hidden Costs

Android Studioで、デフォルトで無効になっているLintがあるので有効にしてこ?などの話があります。

参考

Built-in shrinker