LoginSignup
28
15

More than 5 years have passed since last update.

Flutter for Android の ABI (armeabi-v7a と arm64-v8a)

Last updated at Posted at 2019-02-19

Flutterはエンジンの低レイヤの部分はC++で書かれています。Androidでは、C/C++部分はlibflutter.soとしてアプリ内に含まれます。Flutter SDKにはビルド済みのlibflutter.soファイルが含まれており、これがそのまま使われるようにアプリはビルドされるため、アプリのビルド時にはNDKは必要ありません。

さて、FlutterでAndroid向けにAPKファイルをビルドする際、ある特定のABIのlibflutter.soファイルのみがAPKファイルに含まれます。デフォルトでは armeabi-v7a です。armeabi-v7a は32bitでも64bitでも実行できるので、多くのAndroidデバイスで実行できます。

一方で、複数のABIを含むユニバーサルなAPKを作ることが、現時点ではできません。

しかし Google Play Store は64bit対応を強く推進しており、64bitの arm64-v8a を使いたい(publishしたい)というニーズもあります。

※念のために書いておきますと armeabi-v7a でも64bit CPUのAndroid端末で実行できます

target-platform

この場合は —target-platform というオプションを使います。

armeabi-v7a をビルド(デフォルト):

flutter build apk —target-platform=android-arm

※指定しない場合のデフォルトですが、明示しています

arm64-v8a をビルド:

flutter build apk —target-platform=android-arm64

APKの中身を見ると、たしかに arm64-v8a に libflutter.so が入っています。

スクリーンショット 2019-02-19 19.36.14.png

※NDKを使わないアプリでは libflutter.so のみになります。スクリーンショットで他の .so があるのはNDKを使っているため。

このようにして、それぞれのAPKファイルができるので、これをPlay Storeに公開すればよいです。

Makefileで以下のようにしておくと、楽だと思います。

android: android-arm android-arm64

android-arm:
    flutter build apk --target-platform=android-arm
    cp build/app/outputs/apk/release/app-release.apk ~/Downloads/myapp-release-arm.apk

android-arm64:
    flutter build apk --target-platform=android-arm64
    cp build/app/outputs/apk/release/app-release.apk ~/Downloads/myapp-release-arm64.apk

ただし、それらのAPKファイルのversionCodeは違っている必要があることは留意してください。gradle内でこのオプションの値を project.property('target-platform') で取得できるので、それで分岐させるとよいと思います。

abiFilters

※これより下が必要になるのはNDKを使っている場合に必要なabiFiltersのための処理についてです。NDKなしでFlutterを使っている場合には不要かもしれません。

CARTUNEではOpenCVを使うためにNDKを使っており、ndkのabiFiltersをFlutterのオプションと揃える必要があるため、gradleファイルで以下のように分岐させています。

versionCode 10203000
versionName "1.2.3"

ndk {
    if (!project.hasProperty('target-platform'))
        abiFilters 'x86'
    else switch (project.property('target-platform')) {
        case 'android-arm64':
            abiFilters 'arm64-v8a'
            versionCode += 2
            break
        case 'android-arm':
            abiFilters 'armeabi-v7a'
            versionCode += 1
            break
        default:
            abiFilters 'x86'
            break
    }
}

※x86があるのは、開発中の flutter run コマンドでエミュレータで起動するため

versionCodeの下一桁をABIのために空けておき、target-platformの分岐で += して切り替えています。

IntelliJ

また、コマンドではなく IntelliJ でアプリを実行する際に、このtarget-platformの切り替えを行うためには、メインメニューの「Run」>「Edit Configurations...」で表示される以下のダイアログでAdditional argumentsに設定しておきます。

2019-02-1813-169a6b89-a622-4de9-bace-4a8fb5bdb5f7.17.27.png

エミュレータ用と実機用で別のConfigurationを用意しておいて、実行時にプルダウンから切り替えて使います。

splits

ちなみにGradleのsplitsで複数のAPKを作ろうとすると、flutter build コマンドは失敗します。

これは、flutterコマンドが出来上がったAPKファイルの有無をチェックしており、splitsでアーキテクチャ名がファイル名に入ることと相性が悪いためです。

buildディレクトリ以下にAPKファイルが生成されるところまでは行くので、エラーを無視してAPKファイルを使うというのはありかもしれません。

28
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
15