Android ARM64bit対応まとめ

やっはろこんこん。明日はクリスマスですね。
がんばりましょう。

Androidの64bit対応について前に調査したことをまとめておきます。
対象はUnityで開発されたアプリを想定しています。
また、実行環境はmacOS Sierraとなっています。（古い

# Android ARM64bit対応とは
[Android Developers Blog](https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html)で2019年8月までにAndroidアプリの64bit対応が必要になることが発表されています。
具体的にはAArch64をサポートするARMv8ベースのCPU向けのビルドが必要となります。
これらのCPU向けのABIがarm64-v8aです。

Unityで開発されたアプリでは、大きく2つの対応が必要となると思います。

* ARM64bitビルドに対応したUnityにバージョンアップする
    * monoでビルドしている場合はIL2CPPビルドにする必要あり
* 内部で使われているネイティブプラグインを64bitのものに差し替える

今回は特にネイティブプラグインまわりについて記載しています。

# Unityのバージョンアップ
Unity2018.2以降のバージョンを選択します。
TargetArchitecturesにARM64が追加されています。
![スクリーンショット 2018-12-21 18.51.48.png](https://qiita-image-store.s3.amazonaws.com/0/146380/81f55377-d3d8-6057-240b-2355cc3a1597.png)
古いUnityではバージョンアップが大変だと思いますが、がんばってください。

※2018/12/25 追記
Unity2017.4.16f1にもAndroid 64bit対応が入っているようです。

# arm64-v8a対応済みのプラグインをアップデートする
よく使われそうなプラグインのアップデートに関して、簡単に記述しておきます。
ここで自前でネイティブプラグインをビルドする必要がなく、通常のアップデートでできる範囲となります。

* [Google Play Game ServiceをUnityで扱うためのプラグイン]((https://github.com/playgameservices/play-games-plugin-for-unity))
ver0.9.51以上でarm64-v8aに対応しています。
リポジトリ内の最新のunitypackageをインポートするだけで取り込めると思います。

* [Firebase](https://firebase.google.com/docs/unity/setup?hl=ja)
ver5.2.0以上で対応されています。古いバージョンが入っている場合は削除してから、再インポートする方が罠がないと思います。 

# その他のプラグインをアップデートする
使っているネイティブプラグインでarm64-v8aをサポートしていない場合があります。
新しいプラグイン導入を検討するか、ソースコードが公開されていれば自前でのビルドが可能な場合があります。

基本的にプラグインは<b>Assets/Plugins/Android/libs/arm64-v8a</b>以下に入れます。

## 自前ビルドの方法
例として、[Google Play Game ServiceをUnityで扱うためのプラグイン]((https://github.com/playgameservices/play-games-plugin-for-unity))の0.9.50以前をarm64-v8aでビルドしてみます。

まず、リポジトリからソースコードをcloneしてきます。

一度、arm64-v8aを追加する前にビルドしてみます。
まず、環境変数を設定します。
ネイティブプラグインをビルドするにあたっては、必ず設定しておく必要があります。

* ANDROID_NDK_ROOT
Android NDKのディレクトリを指定します。Unityの要求バージョンに合わせ<b>r16b</b>を使いました。

* ANDROID_HOME
Android SDKのディレクトリを指定します。Android SDKのバージョンは、compileSdkVersionが27になっていますので、それ以降のバージョンをいれておきます。

* UNITY_EXE
このプラグインはUnityでunitypackageにパッキングするため、UNITY_EXEも設定しておく必要があります。他のプラグインのビルドでは通常不要かと思います。macOSの場合は以下ような形になると思います。

```shell
export UNITY_EXE=/Applications/Unity/Unity.app/Contents/MacOS/Unity
```
それではビルドをしてみます。
プロジェクトルート以下でgradlewを実行します。

```shell
./source/gradlew
```
一旦これで、ビルドができました。

ここから実際にarm64-v8a向けのビルドをしてみます。

次のファイルの35行目ぐらいのndk.abiFiltersに'arm64-v8a'を追記します。
./source/SupportLib/PlayGamesPluginSupport/build.gradle

```gradle
defaultConfig {
    versionName  project.version
    archivesBaseName = project.ext.baseName
    minSdkVersion 14

    ndk.abiFilters 'x86', 'armeabi-v7a', 'arm64-v8a'


    externalNativeBuild {
        cmake {
            cppFlags "-std=c++11 -frtti -Wall -Werror"
            arguments "-DGPG_SDK_PATH=${gpgSdkDir}",
                    "-DANDROID_STL=c++_static",
                    "-DANDROID_TOOLCHAIN=clang"
        }
    }
}
```

これで再度ビルドをしてみましょう

```shell
./source/gradlew
```

ビルドが終わると
./source/SupportLib/PlayGamesPluginSupport/build/output/aar以下にgpgs-plugin-support-release.aarが生成されています。

実際にarm64-v8aが含まれているか確認します。
aarはzipファイルなので、unzipしてみます。

```shell
unzip ./source/SupportLib/PlayGamesPluginSupport/build/outputs/aar/gpgs-plugin-support-release.aar
```
jniディレクトリ以下ににarm64-v8aディレクトリとその下にlibgpg.soが入っていることがわかります。

# まとめ
UnityでAndroidのARM64対応するためには、Unity2018.2以降のバージョンでビルドする必要があります。
また、対応されていないネイティブプラグインはプラグインの再選定もしくは、自前でビルドする必要があります。
自前でビルドする際には以下の設定が必要です。

* Android SDKとNDKを正しく設定する
* abiFilterにarm64-v8aを追記する

Androidアプリ開発の助けになれば幸いです。
最後までお読みいただきありがとうございました。