Refresh/Reload database reference in custom ContentProvider after restore
Asked Answered
P

4

9

I use a ContentProvider in my app and everything works great except for one little issue. I have a backup and restore function that backs up the database to a file on the SD card and then those backup files can be restored to overwrite the current database. This whole process is working, but the ContentProvider still holds the reference/cache to the original database once one of the old backup files is restored. I can't seem to find a way to refresh or reload the database reference in the ContentProvider. I know the restore works because I can see the records in the db with SQLite Editor and when I close and re-open the app, it displays the correct records.

Does anybody know a way to do this? Is there a way to close and re-open the ContentProvider that I'm not seeing?

Physoclistous answered 22/11, 2011 at 23:1 Comment(0)
C
6

Are you maintaining a reference to the actual SQLiteDatabase in your content provider (something like calling SQLiteOpenHelper.getWritableDatabase() in onCreate() and then keeping that reference)? Or do you get the DB object from someplace like a helper in each provider method?

Typically, if you only keep a local reference to the helper and get the writable/readable database instance inside of each method as needed then this problem should go away. If not, perhaps we can take a look at the provider code?

Hope that Helps!

Chessa answered 22/11, 2011 at 23:56 Comment(3)
I am getting a reference from a helper in the onCreate db = new DbAdapter(getContext());. This is what all of the examples show. I thought about doing it in each method, but that seems very inefficient to me and sort of slow. Don't you think? Well, I guess I'll try it that way and see how it works. Isn't that going to leave a bunch of open db objects as well if I have multiple queries/updates or will the ContentProvider manage them properly?Physoclistous
Take a look at how the system providers like AlarmProvider are done as an example of what I'm saying. Getting the helper in onCreate() and then the db type as needed. ContentProvider manages request access for you, that's one of the reasons to use it. This is how I build my providers as well: codesearch.google.com/#cZwlSNS7aEw/packages/apps/DeskClock/src/…Chessa
Ahhh...I see. I'm actually using a dbadapter class that houses my helper and opens the db. I am migrating from a API v7 app to use the new compatibility library. I will separate the helper and try it this way. I guess I just didn't realize I should have just been calling a helper so I thought I was following the examples correctly. Doh! Thanks!Physoclistous
U
29

If you are targeting >= API 5 you can get a reference to your ContentProvider via a ContentProviderClient, and run a method specific to your implementation:

ContentResolver resolver = context.getContentResolver();
ContentProviderClient client = resolver.acquireContentProviderClient("myAuthority");
MyContentProvider provider = (MyContentProvider) client.getLocalContentProvider();
provider.resetDatabase();
client.release();

Add the reset method to your ContentProvider implementation:

public void resetDatabase() {
    mDatabaseHelper.close();
    mDatabaseHelper = new MyDatabaseOpenHelper(context);
}
Unciform answered 23/11, 2011 at 0:20 Comment(3)
Thank you for this also. This is also very useful. I have to accept the previous answer as the correct answer though because it pushed me in the right direction without really having to change much. Thanks!Physoclistous
client.release(); is deprecated. Use close() instead.Barracoon
Refere this one if you want to remove and recreate db. https://mcmap.net/q/1169929/-contentprovider-not-called-oncreate-after-deleting-databaseBarracoon
C
6

Are you maintaining a reference to the actual SQLiteDatabase in your content provider (something like calling SQLiteOpenHelper.getWritableDatabase() in onCreate() and then keeping that reference)? Or do you get the DB object from someplace like a helper in each provider method?

Typically, if you only keep a local reference to the helper and get the writable/readable database instance inside of each method as needed then this problem should go away. If not, perhaps we can take a look at the provider code?

Hope that Helps!

Chessa answered 22/11, 2011 at 23:56 Comment(3)
I am getting a reference from a helper in the onCreate db = new DbAdapter(getContext());. This is what all of the examples show. I thought about doing it in each method, but that seems very inefficient to me and sort of slow. Don't you think? Well, I guess I'll try it that way and see how it works. Isn't that going to leave a bunch of open db objects as well if I have multiple queries/updates or will the ContentProvider manage them properly?Physoclistous
Take a look at how the system providers like AlarmProvider are done as an example of what I'm saying. Getting the helper in onCreate() and then the db type as needed. ContentProvider manages request access for you, that's one of the reasons to use it. This is how I build my providers as well: codesearch.google.com/#cZwlSNS7aEw/packages/apps/DeskClock/src/…Chessa
Ahhh...I see. I'm actually using a dbadapter class that houses my helper and opens the db. I am migrating from a API v7 app to use the new compatibility library. I will separate the helper and try it this way. I guess I just didn't realize I should have just been calling a helper so I thought I was following the examples correctly. Doh! Thanks!Physoclistous
B
1

Here is my solution.

public class DataProvider extends ContentProvider {

    private DataDbHelper dbHelper;

    @Override
    public boolean onCreate() {
        // nothing here
        return true;
    }

    private DataDbHelper getDbHelper() {
        if (dbHelper== null) {
            // initialize
            dbHelper = new DataDbHelper(getContext());
        } else if (dbHelper.getReadableDatabase().getVersion() != DataDbHelper.VERSION) {
            // reset
            dbHelper.close();
            dbHelper = new DataDbHelper(getContext());
        }
        return this.mOpenHelper;
    }
}

query(), insert(), update(), delete() use getDbHelper() to obtain an SQLiteDatabase

The full code of my Android app is available here if you need more info.

Bearer answered 8/4, 2012 at 15:8 Comment(0)
C
0

You can also simply use the delete method without a selection:

context.getContentResolver().delete(YourProvider.CONTENT_URI, null, null);
Cracksman answered 13/10, 2015 at 15:5 Comment(1)
What source do you have for this claim? Seems call would just go to my inplementation of the delete() method, no?Menu

© 2022 - 2024 — McMap. All rights reserved.