Roomに依存するデータベース処理をモジュールmylibraryBが持っており、アプリのモジュールappAがそれに依存している。
構成的にはこんな感じ。
├── appA
│ ├── build.gradle
│ └── src
├── build.gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
├── mylibraryB
│ ├── build.gradle
│ └── src
└── settings.gradle
そんな場合で、かつKotlinの場合に、Roomのマイグレーション用スキーマファイルの出力に試行錯誤したので、覚え書きです。
環境など
ツールなど | バージョンなど |
---|---|
MacbookPro | macOS Catalina 10.15.7 |
Android Studio | 4.1.2 |
Java(JDK) | openjdk version "11.0.10" |
Room | 2.2.6 |
Robolectric | 4.3.1 |
対応方法
基本的な対応方法は以下などにあり、ライブラリになっていない場合はこの通りで問題ないはずです。
https://medium.com/androiddevelopers/7-steps-to-room-27a5fe5f99b2
ライブラリモジュールに実際のDAOなどの定義がある場合は、このままだと上手くいきません。
ライブラリ側のbuild.gradleへの変更
ライブラリモジュール側のbuild.gradleに以下のように設定します。
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt' // 追加
android {
//...
defaultConfig {
//...
// schemaを出力する先を設定
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation":"../appA/schemas".toString()]
}
}
}
// ...
}
dependencies {
//...
// Room用に以下を追加
def room_version = "2.2.6"
api "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
// optional - Kotlin Extensions and Coroutines support for Room
api "androidx.room:room-ktx:$room_version"
}
ライブラリなので、Room関連の依存はimplementation
ではなくapi
にしています。
この設定ですと、appAモジュールの以下の場所にschemas
ディレクトリが作られ、その配下にjsonが吐き出されます。
├── appA
│ ├── build.gradle
│ └── src
│ └── schemas
アプリ側のbuild.gradleへの変更
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
//...
defaultConfig {
//...
//schemaファイル読み出しパスを追加
sourceSets {
debug.assets.srcDirs += files("$projectDir/schemas".toString())
}
}
}
dependencies {
//...
// Room用に以下を追加
def room_version = "2.2.6"
testImplementation "androidx.room:room-testing:$room_version"
}
アプリ側でテストを行うため(※)、exportされたschemaファイルを読み見込めるようにします。
assetsディレクトリに先ほど指定したschemas
フォルダを指定しています。
debug.assets
としているのは、Robolectricでテストしたいからです。サンプルではandroidTest.assets
となっていますが、これだとRobolectricでのテスト(testフォルダに作成する)で読み込めません。
以上の設定でスキーマが吐き出され、マイグレーションテストが出来るようになるはずです。
※実はこのappAは、ライブラリのテストコードだけがあるモジュールになっています。なのでこのように吐き出す設定と、利用する側の設定を分ける必要があったということです。ライブラリモジュール内にテストコードがある場合には、ライブラリのbuild.gradleに両方設定すればよいはずです。
参考サイト
マイグレーションテストの参考に。
https://medium.com/androiddevelopers/testing-room-migrations-be93cdb0d975
複雑なデータベース処理をしている場合の移行ガイド。
https://medium.com/androiddevelopers/incrementally-migrate-from-sqlite-to-room-66c2f655b377
マイグレーションサンプル
https://github.com/android/architecture-components-samples/tree/master/PersistenceMigrationsSample
※上記サンプルはJavaコードとなっています