Actually I have more than a question. If I uninstall an app, the room database also removed. I debugged and checked using File(getDatabasePath("MyInfoDatabase.db").absolutePath).exists() before instantiating a room database. Let's say my app crashed and I uninstalled it and then reinstall the app. So it is not possible to get the old room data.
Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
.createFromFile(File("mypath"))
.build()
If I am not wrong, then I can copy and save the database to a directory and get the old databack while reinstalling using the above method. Is this the right approach? In this approach getExternalStoragePublicDirectory is deprecated now. Should I use MediaStore api for database backup? On the other hand here, it says that room data exists even after uninstalling. Is the room database exists even after uninstalling an app? AFAIK it doesn't exists.
Related
In my app I'm using Room with a prepopulated database myDatabase.db which is then accessed using this code:
private val database = Room
.databaseBuilder(context.applicationContext, AppDatabase::class.java, dbName)
.createFromAsset("myDatabase.db")
.build()
The file myDatabase.db is stored in the /assets/ folder. Then I had to add some new rows in one on my tables in such database. After that, I got an updated myDatabase.db file, which I copied to the /assets/ folder replacing the old file. And here comes the problem: after installing the app, it still uses the old data. I did some searching but I only found results related to migrations. However, in my case, there is no change in the schema of the table, only some new rows are added. Furthermore, I don't understand why the app doesn't pick the new myDatabase.db file and still uses the old one.
The only solution to get the app to use the new file myDatabase.db was to uninstall the app and then install it again, but that's something I'd like to avoid. So, how can I change the file myDatabase.db in assets folder and make the app pick the data in the new file through Room?
Furthermore, I don't understand why the app doesn't pick the new myDatabase.db file and still uses the old one.
A Room database is persistent and lasts until it is deleted. createFromAsset will only be invoked when the database does not exist and hence why, under normal situations it will not replace the existing database.
A solution assuming that the App only reads the pre-populated daatbase is to:-
add either of the fallbackToDestructiveMigration or fallbackToDestructiveMigrationFrom
Increase the database version number
DO NOT have a Migration that covers the old to new version
The migration instead of failing will delete the database and then attempt to create it. In doing so it will create the database from the new asset.
After switching to a room database I deleted the SQLite-Helper Class. But if I install my app the old database is still created on my smartphone.
I opened the the device file explorer and found under my project-folder
/databases with the following databases
local.db which is my old database with date of 1970-01-19 and 2.5 MBytes
local_db which is the new room database
local_db-shm and local_db-wal whhich seem to be some room data
Even if I uninstall the app and reinstall it the local.db appears again. Deleting it does not help too.
But I think that I have deleted all the old SQLiteHelper Code. So does anyone know, where I might find the key to getting rid of the old database?
If the manifest (AndroidMainfest.xml) has android:allowBackup="true", this could result in the data being restored automatically by the backup manager. From your description of the issue this could well be the cause.
Try changing to use android:allowBackup="false", uninstalling the App and then re-installing.
I'm developing an Android app with an embedded SQLite database run with Android Room. I'm moving the app from desktop Java to Android and I need to bring data into the Android database from the old database used with the desktop app. I ran into a problem with Room when I tried using the altered database with my Android app.
I tried taking the database file created by Room and move the data from the old database into this one with a short Java app I coded for this purpose. I simply emptied the relevant tables, read data from the old database and inserted it into the new database.
When I tried moving the database file back to my Android devide and using it with the Android app I got this exception:
Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number.
You can simply fix this by increasing the version number.
If I change the version of the database in my Room database code, Room would then require a piece of code for the migration even though the structure of the database has not been changed:
java.lang.IllegalStateException: A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.
I tried clearing the app data cache and clearing all of its data and even uninstalling the app, then reinstalling it with the modified database file. Didn't make the problem go away. I also tried everything here Room cannot verify the data integrity including setting android:allowBackup="false" in my Manifest, and adding fallbackToDestructiveMigration to my database. After trying fallbackToDestructiveMigration, all of my new database's data was gone. But then I put the altered database file back in again and it worked. To be honest, I'm not entirely sure what step made it work. I think it was increasing the version number, running it with fallbackToDestructiveMigration and then moving the new database file back in again when fallbackToDestructiveMigration had wiped data from the database...
My question is how can Room know the database has been modified when there hadn't been any change to its structure that would make it incompatible with the Entities of my app? And how can know even though I've cleared the app's data from the device? And are there any steps I should take the next time that are not mentioned above? I quess I could just include migration code that does nothing. But that seems kind of silly, I'd like the version number to stay at 1 since the app is in development at the moment.
Add an empty Migration.
private val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
// empty migration.
}
}
if (sInstance == null) {
if (!checkDataBase())
copyDataBase(context)
synchronized(AppDatabase::class) {
sInstance = Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, DATABASE_NAME)
.addMigrations(MIGRATION_1_2)
.build()
}
}
return sInstance!!
You can check out this Migration Guide from Florina Muntenescu to learn more about Migrations
When using Room from the Android Architecture Components, I received the following error when attempting to access the database using a Dagger component:
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: (database path)
I was using Dagger version 2.11 and Room version 1.0.0-alpha7. The error was reproducible on version 1.0.0-alpha5.
This error occurred on any attempt to access the database through a DAO after initialising the database and injecting it into my class.
It's because you are trying to modify the schema of the existing database without giving it any migration information. So basically it attempts to write the new database schema to the existing DB which doesn't work.
There are two ways around this. If you are in your development environment what you can do is fallback to a destructive migration, to do this your database creation code would look something like the following:
MyDatabase myDatabase = Room.databaseBuilder(context, MyDatabase.class, "my-db")
.fallbackToDestructiveMigration()
.build();
This means when you provide the database with an updated or new entity it will do what the answer from #huw said and just delete the database on the application's installation removing all the data from it and give you a fresh install.
The other method is to use a migration function. They are pretty long so unless someone wants me to write it up here I'll leave it for now but basically, the documentation can be found here:
Room DB Migration Documentation
This essentially causes the DB to run some SQL provided by yourself to update the database to the new version. This way you can ensure that none of your data is lost while doing the migration; or as little as possible depending on what you are doing. This is the preferred method for production apps as it means users won't lose their pre-existing data and you won't get a lot of angry reviews/lost customers.
Hope that makes helps!
One solution to this problem was to delete the database file and start again. This was not an issue since I was only testing and could repopulate the database using online data.
To do so either:
App info > Storage > Clear Data
Manually remove the file at /data/data/com.app.example/databases/database.db
I had this kind of exception after not so successful migration. Always double-check the SQL query you use for a migration. You can create a new column with a wrong type of data and the exception's description won't be helpful.
What happens after app upgrade, will it keep the database from previous version or flush out all data?
All application data (including stored files, SharedPreferences, and SQLite databases) is kept during updates.
Note that the SQLiteOpenHelper also provides an onUpgrade() method that you can use to upgrade the SQLite database when the database's schema changes. Do not confuse this with application upgrades though!