はじめに
- 久しぶりにAARを目にする機会があった為、思い出しがてらアウトプットをしてみます。
AARとは
Android ARchive(AAR)はAndroidアプリ開発で使用されるライブラリの配布・保存用ファイル形式(拡張子は .aar)です。
Android のリソースとマニフェスト ファイルを含めることができるため、Kotlin または Java のクラスとメソッドに加え、レイアウトやドローアブルなどの共有リソースも扱うことができます。
また、アプリ モジュールの C/C++ コードで使用する C/C++ ライブラリを含めることができるようです。
主に以下の用途に使用できます。
- アクティビティ、サービス、UI レイアウトといった同じコンポーネントを使用する複数のアプリをビルドする場合
- 共通化できて便利
- サードパーティ製のライブラリをアプリへ組み込む際に使用
JARとの違い
- JARは主に純粋なJava/Kotlinプログラムのみ
- Android特有のリソースや設定ファイル(UI部品やレイアウトなど)は含まれない
種類
- デフォルトでdebug.aarとrelease.aarの2種類存在している
- リリース用とデバッグ用という理解でOK
- debug.aar:デバッグができる(デバッグログ出力など)
- release.aar:デバッグができない(圧縮と難読化が行われる)
補足:正確には固定の2種類というより、build.gradleで定義したbuildTypeごとに生成される命名規則。
独自にstagingというbuildTypeを定義すればstaging.aarのような出力も可能。
AARの作成方法について
- 公式ドキュメントを参考
- AARファイルを一から作る場合、モジュール単体のプロジェクトは作れない
- 一度Androidプロジェクトを作成しそこからモジュールを新規作成が必要
ビルド
-
./gradlew :newlibrary:assembleRelease- newlibrary部分はモジュール名
別プロジェクトへの組み込み(試し)
- プロジェクトの
libsにaarを配置 - build.gradle.kts(:app)に依存関係追加
implementation(files("libs/newlibrary-release.aar"))
- sync実行でプロジェクトからaarの処理の呼び出しが可能になる
- 呼び出す際にはライブラリのパッケージ名でimportする必要がある
ちょっと動かしてみる(参考)
今回は「呼び出し元から、AAR内のSettingsActivityにタイトルや戻るボタンの表示有無を設定して画面を開く」という想定で実装してみた。
- ライブラリ側のエントリを用意
// IntentのextraとしてActivity間を跨いで渡すには、
// SettingsConfigがParcelableを実装している必要がある。
// @Parcelizeはそのボイラープレート(writeToParcel/CREATORなど)を自動生成してくれる。
@Parcelize
data class SettingsConfig(
val title: String = "",
val showBackButton: Boolean = true
) : Parcelable
object SettingsActivityLauncher {
fun createIntent(context: Context, config: SettingsConfig): Intent {
return Intent(context, SettingsActivity::class.java).apply {
putExtra(SettingsActivity.EXTRA_CONFIG, config)
}
}
}
- 呼び出し側
@Composable
fun OpenAarScreenButton() {
val context = LocalContext.current
Button(
onClick = {
val config = SettingsConfig(title = "AAR画面", showBackButton = true)
val intent = SettingsActivityLauncher.createIntent(context, config)
context.startActivity(intent)
},
) {
Text("AAR画面を開く", fontSize = 20.sp)
}
}
- 左(アプリ)のボタンを押下すると右(AAR)の画面に遷移(AARのActivityを起動)できた
注意
今回はimplementation(files("libs/newlibrary-release.aar"))という、AARファイルを直接指定する方式で組み込んだ。
この方式はAARファイル自体は持ち込めるが、ライブラリ側が外部ライブラリ(今回で言うとJetpack Compose等)に依存している場合、その推移的依存関係(transitive dependency)は自動解決されない。
ライブラリの依存先を組み込み先で揃えていない場合は、利用側で同じ依存を別途追加する必要がある。
依存関係も含めて配布したい場合は、maven-publishプラグインでローカルMavenリポジトリにpublishし、POM経由で依存解決させる方式が推奨される。
参考:https://developer.android.com/build/publish-library/upload-library
処理の補足
Activity間でデータを受け渡す場合、Intentのextraという仕組みを使うのが基本だが、extraに渡せるのはプリミティブ型(String、Intなど)か、ParcelableまたはSerializableを実装したオブジェクトに限られる。今回のように複数のプロパティをまとめて1つの設定オブジェクトとして渡したい場合は、独自のdata classをParcelable化しておく必要がある。
-
Parcelableにする理由- Intentのextraの実体であるBundleに独自クラスを乗せるための仕組みが、Parcelable/Serializableの2択になっている
- Serializableはリフレクションベースで処理が遅く、Androidでは基本的にParcelableが推奨されている
-
@Parcelizeをつける理由- Parcelableを自前実装すると、プロパティを追加するたびに
writeToParcel/describeContents/CREATORを手書きし直す必要があり面倒 - Kotlinの
@Parcelize(kotlin-parcelizeプラグイン)を使うと、このボイラープレートを自動生成してくれる - 利用するには
build.gradle.ktsにid("kotlin-parcelize")の追加が必要
- Parcelableを自前実装すると、プロパティを追加するたびに
-
@Parcelizeをつけない場合、以下のようにwriteToParcel/describeContents/CREATORを手書きする必要がある- プロパティが増えるたびにこれを修正し続ける必要がある
class SettingsConfig(
val title: String,
val showBackButton: Boolean
) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString()!!,
parcel.readByte() != 0.toByte()
)
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(title)
parcel.writeByte(if (showBackButton) 1 else 0)
}
override fun describeContents(): Int = 0
companion object CREATOR : Parcelable.Creator<SettingsConfig> {
override fun createFromParcel(parcel: Parcel) = SettingsConfig(parcel)
override fun newArray(size: Int): Array<SettingsConfig?> = arrayOfNulls(size)
}
}
まとめ
- AARはAndroid特有のリソースやマニフェストを含められるライブラリ配布形式
-
files()でのローカル参照は手軽だが、推移的依存が解決されない点に注意 - 継続的に配布・運用する場合はリポジトリ経由での公開が推奨される

