Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices for exposing multiple tables using content providers in Android

I'm building an app where I have a table for events and a table for venues. I want to be able to grant other applications access to this data. I have a few questions related to best practices for this kind of problem.

  1. How should I structure the database classes? I currently have classes for EventsDbAdapter and VenuesDbAdapter, which provide the logic for querying each table, while having a separate DbManager (extends SQLiteOpenHelper) for managing database versions, creating/upgrading databases, giving access to database (getWriteable/ReadeableDatabase). Is this the recommended solution, or would I be better off either consolidating everything to one class (ie. the DbManager) or separation everything and letting each Adapter extends SQLiteOpenHelper?

  2. How should I design content providers for multiple tables? Extending the previous question, should I use one Content Provider for the whole app, or should I create separate providers for Events and Venues?

Most examples I find only deal with single table apps, so I would appreciate any pointers here.

like image 364
Gunnar Lium Avatar asked Sep 28 '10 14:09

Gunnar Lium


People also ask

What are the permissions required for the use of content providers in Android applications?

To retrieve data from a provider, your application needs "read access permission" for the provider. You can't request this permission at run-time; instead, you have to specify that you need this permission in your manifest, using the <uses-permission> element and the exact permission name defined by the provider.

What is the main usage of content provider in Android?

The role of the content provider in the android system is like a central repository in which data of the applications are stored, and it facilitates other applications to securely access and modifies that data based on the user requirements.

What is the relation between content provider and content resolver in Android applications?

Content Resolver resolves a URI to a specific Content provider. Content Provider provides an interface to query content. The way to query a content provider is contentResolverInstance.


1 Answers

It's probably a bit late for you, but others may find this useful.

First you need to create multiple CONTENT_URIs

public static final Uri CONTENT_URI1 =      Uri.parse("content://"+ PROVIDER_NAME + "/sampleuri1"); public static final Uri CONTENT_URI2 =      Uri.parse("content://"+ PROVIDER_NAME + "/sampleuri2"); 

Then you expand your URI Matcher

private static final UriMatcher uriMatcher; static {     uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);     uriMatcher.addURI(PROVIDER_NAME, "sampleuri1", SAMPLE1);     uriMatcher.addURI(PROVIDER_NAME, "sampleuri1/#", SAMPLE1_ID);           uriMatcher.addURI(PROVIDER_NAME, "sampleuri2", SAMPLE2);     uriMatcher.addURI(PROVIDER_NAME, "sampleuri2/#", SAMPLE2_ID);       } 

Then create your tables

private static final String DATABASE_NAME = "sample.db"; private static final String DATABASE_TABLE1 = "sample1"; private static final String DATABASE_TABLE2 = "sample2"; private static final int DATABASE_VERSION = 1; private static final String DATABASE_CREATE1 =     "CREATE TABLE IF NOT EXISTS " + DATABASE_TABLE1 +      " (" + _ID1 + " INTEGER PRIMARY KEY AUTOINCREMENT," +      "data text, stuff text);"; private static final String DATABASE_CREATE2 =     "CREATE TABLE IF NOT EXISTS " + DATABASE_TABLE2 +      " (" + _ID2 + " INTEGER PRIMARY KEY AUTOINCREMENT," +      "data text, stuff text);"; 

Don't forget to add the second DATABASE_CREATE to onCreate()

You are going to use a switch-case block to determine what table is used. This is my insert code

@Override public Uri insert(Uri uri, ContentValues values) {     Uri _uri = null;     switch (uriMatcher.match(uri)){     case SAMPLE1:         long _ID1 = db.insert(DATABASE_TABLE1, "", values);         //---if added successfully---         if (_ID1 > 0) {             _uri = ContentUris.withAppendedId(CONTENT_URI1, _ID1);             getContext().getContentResolver().notifyChange(_uri, null);             }         break;     case SAMPLE2:         long _ID2 = db.insert(DATABASE_TABLE2, "", values);         //---if added successfully---         if (_ID2 > 0) {             _uri = ContentUris.withAppendedId(CONTENT_URI2, _ID2);             getContext().getContentResolver().notifyChange(_uri, null);             }         break;     default: throw new SQLException("Failed to insert row into " + uri);     }     return _uri;                 } 

You will need to devide up the delete, update, getType, etc. Wherever your provider calls for DATABASE_TABLE or CONTENT_URI you will add a case and have DATABASE_TABLE1 or CONTENT_URI1 in one and #2 in the next and so on for as many as you want.

like image 87
Opy Avatar answered Oct 06 '22 03:10

Opy