fabricプラグインを入れるとInstantRun時にABIs APK Splitのアーキテクチャがx86になるのを回避する


Realmを使っているアプリではAPKの肥大化を防ぐためにアーキテクチャ毎にAPKを分けるようにするのが定石です。

異なるアーキテクチャのAPKをPlayストアで公開するためにはVersionCodeを各アーキテクチャ毎に異なったものを設定する必要があります。

そんなアプリでInstantRunを有効にしてみたところ、なぜかABIがx86として扱われてしまいました。
具体的には

app/build.gradle
...
    // アーキテクチャ毎にバージョンコードを変更する
    applicationVariants.all { variant ->
        // assign different version code for each output
        variant.outputs.each { output ->
            def flavorName = variant.productFlavors[0].name
            def buildTypeName = variant.buildType.name

            def arch = output.getFilter(com.android.build.OutputFile.ABI)
            output.versionCodeOverride = android.defaultConfig.versionCode * 10 + rootProject.ext.versionCodes.get(arch)

            System.println("* override version code : [${android.defaultConfig.versionCode}] -> [${output.versionCodeOverride}] (${flavorName} ${buildTypeName} ${arch})")
        }
    }

こうすると下記のようにバージョンコードが書き換わります。

* override version code : [6] -> [62] (premium debug x86)
* override version code : [6] -> [64] (premium debug armeabi-v7a)
* override version code : [6] -> [62] (premium release x86)
* override version code : [6] -> [64] (premium release armeabi-v7a)
* override version code : [6] -> [62] (free debug x86)
* override version code : [6] -> [64] (free debug armeabi-v7a)
* override version code : [6] -> [62] (free release x86)
* override version code : [6] -> [64] (free release armeabi-v7a)

これを普通にAndroidStudioから実行すると VersionCode=64 のほうがインストールされます。

しかし、InstantRun を有効にして実行すると VersionCode=64 のほうがインストールされてしまい、再インストールを促されてしまいました。

色々調べたところ、fabric プラグインを入れることでこの現象が発生するようです。

classpath 'io.fabric.tools:gradle:1.21.7'

前置きが長くなりましたが、これを解消するために debug 版では バージョンコードの下一桁を 0 にするようにしてみました。

app/build.gradle
...
    // アーキテクチャ毎にバージョンコードを変更する
    applicationVariants.all { variant ->
        // assign different version code for each output
        variant.outputs.each { output ->
            def flavorName = variant.productFlavors[0].name
            def buildTypeName = variant.buildType.name

            def arch = output.getFilter(com.android.build.OutputFile.ABI)
            def versionCode1 = rootProject.ext.versionCodes.get(arch)
            if (buildTypeName == "debug") {
                // InstantRun を有効にすると fabric プラグインの影響で ABI が "x86" になってしまい、
                // InstantRun の有効/無効でバージョンコードが変化してしまう。これを防ぐためデバッグ時は "0" にする。
                versionCode1 = 0;
            }
            output.versionCodeOverride = android.defaultConfig.versionCode * 10 + versionCode1

            System.println("* override version code : [${android.defaultConfig.versionCode}] -> [${output.versionCodeOverride}] (${flavorName} ${buildTypeName} ${arch})")
        }
    }

下記のように書き換わっているので大丈夫そうです。

* override version code : [6] -> [60] (premium debug x86)
* override version code : [6] -> [60] (premium debug armeabi-v7a)
* override version code : [6] -> [62] (premium release x86)
* override version code : [6] -> [64] (premium release armeabi-v7a)
* override version code : [6] -> [60] (free debug x86)
* override version code : [6] -> [60] (free debug armeabi-v7a)
* override version code : [6] -> [62] (free release x86)
* override version code : [6] -> [64] (free release armeabi-v7a)