TL;DR
- 結果
# ls -l *.apk
-rwxrwxrwx 1 kabocha kabocha 293997572 Nov 14 20:22 original.apk*
-rwxrwxrwx 1 kabocha kabocha 289364774 Nov 14 20:54 minifyEnabled_shrinkResources.apk*
-rwxrwxrwx 1 kabocha kabocha 97902257 Nov 14 21:34 abiFilters.apk*
-rwxrwxrwx 1 kabocha kabocha 49605621 Nov 14 22:48 extractNativeLibs.apk* # 最終結果
(49605621/293997572)*100 ≒ 16.87...
-
app/build.gradle
で,ndk.abiFilters
を指定
android {
defaultConfig {
// arm64のみサポートする.
ndk {
abiFilters 'arm64-v8a'
}
-
AndroidManifest.xml
でapplication.android:extractNativeLibs
をtrue
に指定 -
app/build.gradle
で,buildTypes.minifyEnabled, buildTypes.shrinkResources
をtrue
に指定
APKサイズがでかいんじゃ
かぼちゃです.普段,Androidの組み込みエンジニアとして働いています.
Google Play Storeに新規で公開するには,Android App Bundle でないといけなくなりましたので,そろそろAPK自体使われなくなりそうな風潮もありますが,組み込みAndroidにおいては,プリインストールする際などには,ソースコードもしくは,APKが必要です.
さて,お仕事の中で,取り込んでいるAARやライブラリの都合で1つのAPKだけで,300MB近いものをプリインストールしなければならない事態になりました.
もちろん,技術的には問題ありませんが,例えばFOTAでそのアプリを更新するとなると,その分の差分が大きくなりますので,ユーザーが負担する通信コストも肥大化してしまいます.
(Androidの差分FOTAは非常に優秀なので,そこまで大きくはなりませんが...)
こういった背景から,このでかすぎるAPKのサイズを,小さくしていく中で,特に効果的だったものを書かせていただいています.
なお,今回は実装の変更等はせず,設定周りだけを修正していますので,取り込みやすいかもしれません.また前提として,今回は Android StudioでGradleを使って,ビルド・開発するものとします.
ndk.abiFilters (およそ 67% 削減)
NDKで開発されたことがある人は,ご存知かもしれません.Android Developerから引用すると,
Gradle はデフォルトでは、NDK がサポートするアプリケーション バイナリ インターフェース(ABI)の個々の .so ファイルにネイティブ ライブラリをビルドし、それをすべてアプリにパッケージ化します。Gradle を使ってネイティブ ライブラリの特定の API 設定のみビルドしてパッケージ化したい場合は、下記に示すように、モジュール レベルの build.gradle ファイル内で ndk.abiFilters フラグを使って指定できます。
とあります.つまり特に指定とかをしていない場合だと,エミューレータでも動くように,x86_64
向けなどの .so
ライブラリをビルドして,APKに入れてしまっているわけですね.
一般的なAndroidデバイスだと,arm系がほとんどだと思いますので,削れそうです.(Google Play Store等に公開するときは怒られる気がします.)
まして,私のような組み込みAndroidの場合,極端な話動作保証をするハードウェアが限られてきますので,不要な構成をビルドする理由はなさそうです.
arm64-v8a
のみを対象にしてビルドしてみると,適応前のおよそ33%にまでバイナリサイズを抑えることができました.
およそ290MB → およそ98MB
参考,引用
application.android:extractNativeLibs (およそ 50% 削減)
Android Developerから引用すると
パッケージ インストーラがネイティブ ライブラリを APK からファイル システムに抽出するかどうかを指定します。false に設定した場合、ネイティブ ライブラリは、ページ アライメントを行ったうえで、圧縮せずに APK 内に保存する必要があります。実行時にリンカーが直接 APK からライブラリをロードするため、コードを変更する必要はありません。
とあります.いかにも,デフォルト true
のような記述になっていますが,Android Gradle プラグイン 3.6.0 のリリース を確認すると,デフォルトで false
にしているという記述がありました.これも,APKサイズが大きくなってしまう原因となっているようなので,有効にしました.
およそ98MB → およそ50MB
参考,引用
- https://developer.android.com/guide/topics/manifest/application-element
- https://developer.android.google.cn/studio/releases/gradle-plugin?hl=ja
buildTypes.minifyEnabled, buildTypes.shrinkResources (およそ 数MB 削減)
説明はDeveloperサイトで行われていますので,割愛します.
参考
終わりに
結果として,もともとの15%近いAPKサイズにまで小さくすることができました.
もちろん,APKに占める割合にリソースファイルが大多数のときなどは,今回のアプローチだけでは難しいですが,一助になれば幸いです.