アプリの最適化を有効にすると、オプティマイザーのデフォルトの動作は R8 のバージョンによって異なります。
- AGP 9.3 以降で利用可能な更新された DSL では、最適化が有効になっている場合、リソースの縮小がデフォルトで有効になっています。コードとリソースの最適化を個別に有効にする必要がある以前の DSL は、引き続きサポートされています。
AGP 9.3 より前のバージョンでは、
isShrinkResources = true設定により、未使用のリソースを削除するようオプティマイザーに指示し、アプリのサイズを縮小できます。リソースの圧縮はコードの圧縮と組み合わせてのみ機能するため、リソースを最適化する場合はisMinifyEnabled = trueも設定してください。
AGP 9.3 以降(Kotlin)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
AGP 9.3+(Groovy)
buildTypes {
release {
optimization {
enable = true // Enables code and resource optimizations.
}
}
}
以前の DSL(Kotlin)
buildTypes {
release {
isMinifyEnabled = true
isShrinkResources = true
...
}
}
レガシー DSL(Groovy)
buildTypes {
release {
minifyEnabled = true
shrinkResources = true
...
}
}
特定のリソースを保持または破棄する場合は、プロジェクト リソース(例: res/raw/keep_my_package.xml)に XML 保持ファイルを作成します。キープファイルには次のコンポーネントがあります。
<resources>タグ - すべての子リソース要素と keep/discard 属性が含まれます。tools:keep属性 - 保持するリソースを識別するリソース名のカンマ区切りのリストを受け入れますtools:discard属性 - 破棄するリソースを識別するリソース名のカンマ区切りのリストを受け入れます
アスタリスク文字をワイルドカードとして使用して、同じフォルダ内の複数のリソースを参照します。例:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard="@layout/unused2" />
破棄するリソースを指定することは、削除できるのに余計なことのように思えるかもしれませんが、ビルド バリアントを使用する場合にはリソースの破棄が役立つことがあります。
特定のビルド バリアントをターゲットにする
一部のビルド バリアントでのみリソースを削除するには、すべてのリソースを共通のプロジェクト ディレクトリに配置し、バリアントのリソース ディレクトリに各ビルド バリアント用の異なる keep_my_package_build_variant.xml ファイルを作成します。キープファイルで、特定のビルド バリアントでは実際には使用されないことがわかっているにもかかわらず、コードで使用されているように見える(そのため、シュリンカーによって削除されない)リソースを削除するよう手動で指定します。
未使用の代替リソースの削除
オプティマイザーは、アプリのコードで参照されていないリソースのみを削除します。つまり、さまざまなデバイス構成の代替リソースは削除されません。
アプリのモジュールの build.gradle ファイルで Android Gradle の resConfigs プロパティを使用して、アプリに不要な代替リソース ファイルを削除します。
たとえば、言語リソースを含むライブラリ(Google Play 開発者サービスなど)を使用している場合、アプリの他の部分が同じ言語に翻訳されているかどうかに関係なく、それらのライブラリのメッセージの翻訳済みのすべての言語文字列がアプリに含まれることになります。アプリが公式にサポートする言語のみ保持するようにするには、resConfigs プロパティを使用してそれらの言語を指定します。指定しない言語のリソースは削除されます。
次のスニペットは、言語リソースを英語とフランス語のみに限定する方法を示しています。
android {
defaultConfig {
...
resourceConfigurations.addAll(listOf("en", "fr"))
}
}
または
android {
defaultConfig {
...
resConfigs "en", "fr"
}
}
Android App Bundle(AAB)形式を使用してアプリを公開すると、デフォルトでは、ユーザーがアプリをインストールする際に、ユーザーのデバイスで設定されている言語のみがダウンロードされます。同様に、デバイスの画面密度に一致するリソースと、デバイスの ABI に一致するネイティブ ライブラリのみがダウンロードに含まれます。詳細については、構成 APK のタイプを再度有効または無効にするをご覧ください。
APK でリリースされる以前のアプリ(2021 年 8 月より前に作成されたアプリ)の場合、さまざまなデバイス構成を対象とする複数の APK をビルドすることで、APK に含める画面密度または ABI リソースをカスタマイズできます。
リソースをマージする際の競合を回避する
デフォルトでは、Android Gradle プラグイン(AGP)は、同じ名前のリソース(異なるリソース フォルダにある同じ名前のドローアブルなど)をマージします。この動作は shrinkResources プロパティで制御されず、無効にすることもできません。これは、複数のリソースにコードが参照している名前が付けられている場合にエラーを回避するために必要な動作であるためです。
リソースのマージは、2 つ以上のファイルが同じリソース名、タイプ、修飾子を共有している場合にのみ発生します。AGP は、重複するファイルの中から最適なファイル(後述の優先順位に基づく)を選択し、そのリソースのみを AAPT に渡して最終ビルド アーティファクトに含めます。
AGP は、次の場所で重複するリソースを探します。
- メイン ソースセットに関連付けられたメイン リソース(通常は
src/main/res/にあります) - ビルドタイプとビルド フレーバーからなるバリアント オーバーレイ
- ライブラリ プロジェクトの依存関係
AGP は、次の優先順位で重複するリソースをマージします。
たとえば、重複するリソースがメイン リソースとビルド フレーバーの両方に存在する場合、Gradle はビルド フレーバーのリソースを選択します。
同じソースセットに同一のリソースが含まれている場合、Gradle はそれらをマージできず、リソース マージエラーを返します。これは、モジュールの build.gradle ファイルの sourceSet プロパティで複数のソースセットを定義した場合に発生する可能性があります。たとえば、src/main/res/ と src/main/res2/ の両方に同じリソースが含まれている場合などです。
リソース圧縮のトラブルシューティング
リソースを縮小すると、[ビルド] ウィンドウに、アプリから削除されたリソースの概要が表示されます(ウィンドウの左側にある [ビューを切り替え] をクリックすると、Gradle からのテキスト出力の詳細が表示されます)。次に例を示します。
:android:shrinkDebugResources
Removed unused resources: Resource data reduced from 2570KB to 1711KB: Removed 33%
:android:validateDebugSigning
Gradle は、<module-name>/build/outputs/mapping/release/(ProGuard 出力ファイルと同じフォルダ)に resources.txt という名前の診断ファイルも作成します。このファイルには、どのリソースが他のリソースを参照しているか、どのリソースが使用または削除されているかなどの詳細が含まれています。
たとえば、@drawable/ic_plus_anim_016 がアプリに残っている理由を調べるには、resources.txt ファイルを開いてそのファイル名を検索します。別のリソースから参照されていることがわかります。
16:25:48.005 [QUIET] [system.out] @drawable/add_schedule_fab_icon_anim : reachable=true
16:25:48.009 [QUIET] [system.out] @drawable/ic_plus_anim_016
ここで、@drawable/add_schedule_fab_icon_anim に到達できる理由を知る必要があります。上に検索すると、resources.txt の The root reachable resources are: という見出しの下にリソースがリストされています。
これは、add_schedule_fab_icon_anim へのコード参照があること、つまり、到達可能なコードで R.drawable ID が見つかったことを意味します。
厳密なチェックを使用していない場合、動的に読み込まれたリソースのリソース名の構築に使用される可能性のある文字列定数がある場合、リソース ID は到達可能としてマークされます。この場合、ビルド出力でリソース名を検索すると、次のようなメッセージが表示されることがあります。
10:32:50.590 [QUIET] [system.out] Marking drawable:ic_plus_anim_016:2130837506
used because its format-string matches string pool constant ic_plus_anim_%1$d.
これらの文字列のいずれかが表示され、その文字列が特定のリソースを動的に読み込むために使用されていないことが確実な場合は、キープファイルの tools:discard 属性を使用して、ビルドシステムにリソースを削除するよう通知します。