we are using ormlite successfully in our android application; for maintaining database versions, we use an approach like here:
http://www.michenux.net/android-database-sqlite-creation-upgrade-245.html
Lately, we've seen "paranormal activity" in the field with apps being in databases states they could not "sanely be", and are trying to find explanations.
One could be that, when a running App is upgraded automatically by Google Play, the onUpgrade() is executed, changing tables and data, while the old (or the new?) App, or maybe their IntentServices concurrently access the database, and get strange results.
(Sadly, there is no easy way to just say "completely stop my app before upgrade, do the upgrade, then completely restart". There is the MY_PACKAGE_REPLACED intent, but opinions on how to use it greatly vary...)
So my question is, is there any safeguard in place that will make onUpgrade() run exclusively, i.e. blocking or locking or synchronizing anything, to make sure another thread does not access my table while I e.g. drop a column (i.e. rename, recreate, copy over data from old tab).
If no, how could I achieve such a thing in the safest way ?
Thanks & kind regards.
Okay, so -
the thorough analysis exposed another (handmade) issue (in our code) that caused all those problems.
So, not to spread any rumours: It seems there is no race condition in onUpgrade() !
It would have been nice to know if it is good practice to have an (exclusive?) transaction block for onUpgrade(), though...
I do have one migration using begin transaction, und sqlite throws an error upon nested transactions, so I am pretty sure there is none around onUpgrade() automatically.
For clarification on other issues
Yes, Apps are terminated before being upgraded.
Only Services might need to re-read config, and alarms (timers) might need restarting.
Related
i converted my android app from mapdb to objectbox, i've seen on github a few people reporting database corruption with objectbox and the solution has always been to call usePreviousCommit in case of problems.
since the objectbox core is close source I wanted to know what usePreviousCommit does internally
are there 2 physical copies of the database? and calling usePreviousCommit reverts to the previous copy?
or does it work in a more complex way? (if yes i wanted to know how)
i opened this question because i want more information from objectbox before i continue to use it in production.
The key word is multiversion-concurrency. Think of a B+ tree with copy-on-write. The previous root tree (aka the previous commit) is preserved, so you can use when opening.
so I made a basic application using the Room ORM to take care of my persistence (which uses SQLite). I'm a huge fan of SQLite myself, and am very familiar with it, such is why I chose room.
But every time I run my app, I get close to 1000 lines of warnings of "Accessing hidden field Landroid/database/sqlite/SQLiteDatabase;->.... " (the .... part is slightly different with every warning message).
From my understanding, that means I'm accessing non-sdk interfaces that may be removed in future versions without notice.
In which case, does that mean that SQLLite is deprecated in Android? I couldn't find any source online saying such a thing. But I really can't understand why else I'd be getting so many of these warnings.
Or is it just that Room is outdated? I tried with both android 11 and 10 and had the same problem.
I saw one other solution here which was to try and close the "Database Inspector" bundled with Android studio. Problem is: I'd like to use it, and every time I close it/remove from sidebar, it opens itself back up on the next run of my app.
Just wondering what the situation is here. Hopefully someone can help.
In which case, does that mean that SQLLite is deprecated in Android?
No.
Or is it just that Room is outdated?
No.
every time I run my app, I get close to 1000 lines of warnings of "Accessing hidden field Landroid/database/sqlite/SQLiteDatabase;->.... " (the .... part is slightly different with every warning message).
From my understanding, that means I'm accessing non-sdk interfaces that may be removed in future versions without notice.
Something — Room or Database Inspector, most likely, given your description — is using greylisted APIs. Room is created by Google. Database Inspector probably is created by Google (if not, it would be JetBrains). The decision of what hidden APIs get on the greylist is made by Google.
So, at some point, Google will need to talk to Google and decide what to do about Google's decision that affects Google's code. It is extraordinarily unlikely that some future version of Android will be released that somehow breaks Room and/or Database Inspector.
So, your focus for those warnings is whether you directly are using those hidden APIs. If you are not, then I would not spend much time worrying about it.
So I am creating this application where there are lots of personal information and data which shouldn't be persisted in the device to avoid security issues. When learning about Room, I came across this Room.inMemoryDatabaseBuilder() which as the documentation states:
Creates a RoomDatabase.Builder for an in memory database. Information stored in an in memory database disappears when the process is killed. Once a database is built, you should keep a reference to it and re-use it.
I was wondering whether this would be a perfect usecase for my situation. Since the data will only exist in memory and not stored in the device.
It seems like a good idea. My only concern is that I haven't seen an implementation of this in an actual application yet. The only usecase which I saw this Room.inMemoryDatabaseBuilder() used was for testing (so then you don't have to worry about database clean-up on each and every test run).
Can anyone offer some advice? It would be much appreciated.
Thank you very much.
I posted this same context question in #Florina Muntenescu Blog here
Her answer was:
Hi,
Yes, it can be used for any use case that requires the data to be kept in memory only. Testing is one of them.
So basically, Room.inMemoryDatabaseBuilder() can be used for other use cases where data should only be kept in memory.
Room.inMemoryDatabaseBuilder() has been designed mostly for testing purposes. I would never use it in production because you can't know when the process is killed by the system, so any use which goes above an advanced structured cache or similar is probably not a good idea.
I think you have a lot of options to solve the problem without relying on this API.
You can use one or more of the following options:
Encrypt Room database using SQLCipher and store it in application private folder.
Use the Android Keystore to store private information or passwords to access personal information.
Block some sensitive part of your application if the device is rooted using SafetyNet api
Don't store sensitive data in database at all, but ask for them to the server at runtime only when explicitly requested by the user.
I've been messing around with an Android project that uses a room database. Because I didn't design the database before I started (I didn't initially plan to even use one), it has a bunch of migrations that drop and recreate tables all over again.
I've never released the app since it's kind of a learning project, but if I ever show anyone I'd rather not show them the 3 migrations in a row where I drop and recreate the table. Is there a way just to tell it to use a completely new schema, as if it had never used one before?
Turns out I hadn't been wording my Google searches properly. I should have searched for how to reset to version 1 since that's a lot clearer than dropping tables or schemas.
See this stackoverflow link below to see what answered my question:
Room persistent library reset version to 1
I'm looking to implement my first Android database, but I have so many questions which (I believe) are unanswered by all the tutorials I find.
Here are my needs:
- I want my application to have a database that is persistent. If my application closes and launches again, there is already a database to pull data from. It does not create a new database every time the application is killed and re-launched.
- I want to implement versioning. Say version 1 of my application has a few tables. I release version 2 and I want some sort of script to run to add new tables I've added or modify old tables I've added; and so on and so forth. The application has to know whether the database is at a particular version (which means I'll need a table in the database) so it knows whether to run this script.
Could someone provide me with some resources so I can figure out how to do what I need? Thank you
Look for sqlite+android+tutorial:
http://www.hdelossantos.com/2009/12/23/creating-a-sqlite-database-in-android/
http://www.hdelossantos.com/2010/01/07/using-a-sqlite-database-in-android/
and some more:
http://www.google.com.hk/search?sourceid=chrome&ie=UTF-8&q=android+sqlite+tutorial
There is also a sample in the sample programs that come with the SDK, i.e. the Notepad app.
And the official developer api doc - but that's more as a reference, not as tutorial:
http://developer.android.com/reference/android/database/sqlite/package-summary.html