Issue
I have a app which is working fine with SQLite
database. I wanted to upgrade to Room
and I followed this and this articles to test and upgrade from SQLite to Room.
I have created Entities
,DAO
and Database
classes.
Following is my (build.gradle:app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
applicationId "APP ID"
minSdkVersion 20
targetSdkVersion 28
versionCode 10
versionName "1.4.5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
sourceSets {
androidTest.assets.srcDirs += files("$projectDir/schemas".toString())
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
repositories {
maven {
url 'http://dl.bintray.com/amulyakhare/maven'
}
}
}
dependencies {
def room_version = "1.1.1"
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Core library
androidTestImplementation 'androidx.test:core:1.0.0'
androidTestImplementation "androidx.test.ext:junit:1.0.0"
androidTestImplementation 'androidx.test:rules:1.1.0'
androidTestImplementation 'android.arch.persistence.room:testing:1.1.1'
implementation "androidx.room:room-runtime:2.1.0-alpha03"
implementation "androidx.appcompat:appcompat:1.0.2"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
implementation 'com.googlecode.libphonenumber:libphonenumber:8.8.1'
implementation 'com.facebook.stetho:stetho:1.5.0'
implementation 'com.google.android.material:material:1.1.0-alpha01'
implementation 'com.hbb20:ccp:2.0.3'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'com.google.firebase:firebase-ads:11.4.2'
implementation 'com.google.firebase:firebase-crash:11.4.2'
}
Following is Test class for creating Database replica
public class SqliteTestDbOpenHelper extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 10;
public SqliteTestDbOpenHelper(Context context, String databaseName) {
super(context, databaseName, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase db) {
String CREATE_CONTACTS_TABLE = "CREATE TABLE " + ContactsDBContract.ContactsTable.TABLE_CONTACTS +
"(" +
ContactsDBContract.ContactsTable._ID + " INTEGER PRIMARY KEY," + // Define a primary key
ContactsDBContract.ContactsTable.CONTACT_ID + " TEXT, " +
ContactsDBContract.ContactsTable.CONTACT_LOOKUP_KEY + " TEXT, " +
ContactsDBContract.ContactsTable.CONTACT_MESSAGE+ " TEXT, " +
ContactsDBContract.ContactsTable.CONTACT_NAME+ " TEXT, " +
ContactsDBContract.ContactsTable.CONTACT_PHONE_NUMBER + " TEXT, " +
ContactsDBContract.ContactsTable.CONTACT_DATA_VERSION+ " TEXT, " +
ContactsDBContract.ContactsTable.CONTACT_STAMP_STATUS+ " TEXT, " +
ContactsDBContract.ContactsTable.CONTACT_MIMETYPE+ " TEXT, " +
ContactsDBContract.ContactsTable.IS_BLOCK+ " INTEGER " +
")";
String CREATE_BLOCK_TABLE = "CREATE TABLE " + ContactsDBContract.BlockTable.TABLE_BLOCKS +
"(" +
ContactsDBContract.BlockTable._ID + " INTEGER PRIMARY KEY," + // Define a primary key
ContactsDBContract.BlockTable.BLOCK_CONTACT_PHONE_NUMBER + " TEXT, " +
ContactsDBContract.BlockTable.BLOCK_CONTACT_NAME+ " TEXT " +
")";
String CREATE_SCHEDULE_TABLE="CREATE TABLE " + ContactsDBContract.ScheduleTable.SCHEDULE_TABLE +
"(" +
ContactsDBContract.ScheduleTable._ID + " INTEGER PRIMARY KEY," + // Define a primary key
ContactsDBContract.ScheduleTable.SCHEDULE_START_TIME + " TEXT, " +
ContactsDBContract.ScheduleTable.SCHEDULE_END_TIME+ " TEXT " +
")";
try {
db.execSQL(CREATE_BLOCK_TABLE);
db.execSQL(CREATE_CONTACTS_TABLE);
db.execSQL(CREATE_SCHEDULE_TABLE);
} catch (SQLException e) {
e.printStackTrace();
FirebaseCrash.report(e);
}
}
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Not required as at version 1
}
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Not required as at version 1
}
}
Below is my Room Database class
@Database(entities = {ContactsData.class,SchedulesData.class,BlocksData.class}, version = 11,exportSchema = true)
public abstract class DatabaseManager extends RoomDatabase {
private DatabaseManager database;
public abstract ContactDao contactsDao();
public abstract SchedulesDao schedulesDao();
public abstract BlocksDao blocksDao();
@VisibleForTesting
public static Migration MIGRATION_10_11 = new Migration(10,11) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
// nothing to do because we did not change anything
}
};
public DatabaseManager getInstance(Context context){
if(database == null){
database = Room.databaseBuilder(context.getApplicationContext(),DatabaseManager.class,"ContactsDB,db")
.addMigrations(MIGRATION_10_11).build();
}
return database;
}
}
And below is my Migration test class
@RunWith(AndroidJUnit4.class)
public class MigrationTest {
private static final String TEST_DB_NAME = "Contactsdb";
// Helper for creating Room databases and migrations
@Rule
public MigrationTestHelper mMigrationTestHelper =
new MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
DatabaseManager.class.getCanonicalName(),
new FrameworkSQLiteOpenHelperFactory());
// Helper for creating SQLite database in version 1
private SqliteTestDbOpenHelper mSqliteTestDbHelper;
@Before
public void setUp() throws Exception {
// To test migrations from version 1 of the database, we need to create the database
// with version 1 using SQLite API
mSqliteTestDbHelper = new SqliteTestDbOpenHelper(ApplicationProvider.getApplicationContext(),
TEST_DB_NAME);
// We're creating the table for every test, to ensure that the table is in the correct state
SqliteDatabaseTestHelper.createTable(mSqliteTestDbHelper);
}
@After
public void tearDown() throws Exception {
// Clear the database after every test
SqliteDatabaseTestHelper.clearDatabase(mSqliteTestDbHelper);
}
@Test
public void migrationFrom1To2_containsCorrectData() throws IOException {
// Create the database with the initial version 1 schema and insert a user
SqliteDatabaseTestHelper.addContact(mSqliteTestDbHelper);
// Create the database with the initial version 1 schema and insert a user
//SqliteDatabaseTestHelper.insertContact(1, "zaid", mSqliteTestDbHelper);
mMigrationTestHelper.runMigrationsAndValidate(TEST_DB_NAME, 11, true,
MIGRATION_10_11);
// Get the latest, migrated, version of the database
DatabaseManager latestDb = getMigratedRoomDatabase();
// Check that the correct data is in the database
List<ContactsData> dbUser = latestDb.contactsDao().getAll();
assertThat(dbUser.size(),is(1));
}
@Test
public void startInVersion2_containsCorrectData() throws IOException {
// Create the database with version 2
SupportSQLiteDatabase db = mMigrationTestHelper.createDatabase(TEST_DB_NAME, 3);
// db has schema version 2. insert some data
insertContact(db);
db.close();
// open the db with Room
DatabaseManager usersDatabase = getMigratedRoomDatabase();
// verify that the data is correct
// Get the latest, migrated, version of the database
DatabaseManager latestDb = getMigratedRoomDatabase();
// Check that the correct data is in the database
List<ContactsData> dbUser = latestDb.contactsDao().getAll();
assertThat(dbUser.size(),is(1));
}
private DatabaseManager getMigratedRoomDatabase() {
DatabaseManager database = Room.databaseBuilder(ApplicationProvider.getApplicationContext(),
DatabaseManager.class, TEST_DB_NAME)
.addMigrations(MIGRATION_10_11)
.build();
// close the database and release any stream resources when the test finishes
mMigrationTestHelper.closeWhenFinished(database);
return database;
}
private void insertContact(SupportSQLiteDatabase db) {
ContentValues cv=new ContentValues();
cv.put(ContactsDBContract.ContactsTable.CONTACT_ID,"212222");
cv.put(ContactsDBContract.ContactsTable.CONTACT_NAME,"Moti");
cv.put(ContactsDBContract.ContactsTable.CONTACT_LOOKUP_KEY,"Okay-uuss");
cv.put(ContactsDBContract.ContactsTable.CONTACT_PHONE_NUMBER,"03215467845");
db.insert(ContactsDBContract.ContactsTable.TABLE_CONTACTS, SQLiteDatabase.CONFLICT_REPLACE, cv);
}
}
But when I run/debug migrationFrom1To2_containsCorrectData()
test. Im getting following error
Cannot find the schema file in the assets folder. Make sure to include the exported json schemas in your test assert inputs. See https://developer.android.com/topic/libraries/architecture/room.html#db-migration-testing for details. Missing file: package.dummy.manager.DatabaseManager/11.json
It seems schemas are not being created at compile time as explained in official docs. May be I'm understanding something wrong
Solution
Your initial setup of Android Room is incorrect. You missed it's annotation processor dependency. As from official documentation which you can find here Adding components # Room - for AndroidX you should have two lines:
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version" // use kapt for Kotlin
Then rebuild project and look inside $projectDir/schemas
folder: your schemas should be inside.
Answered By - Andrei Vinogradov
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.