Android Content Providers

  • Written by  Clive

What you should know about Content providers

Content Provider iconSQLite databases can only be used by the app that created it. However you can choose to share the database with other apps if you wish.

You will need a content provider to manage access to this shared database.

It takes care of data security and communicates between the database and any app wanting to use it.

You’re not restricted to using the content provider with a SQLite database

You can also use content providers to access any source of data including files and application variables.

Your Android device has its own content providers

Android has its own content providers that give you access to its databases such as the media and contacts databases.

A device can have a number of registered content providers. Each must have a unique address.

Do you need a content provider?

You’ll need a content provider if you want to allow other apps to access your database.

You’ll also need a content provider if you want to perform custom search suggestions in your own app.

Content resolver

You create a content provider in the app that creates the database. This allows other apps to use the database.

Any app wanting to use the database must use a content resolver to do so.

Content resolver and content provider 

The Content Resolver communicates with the Content Provider

Let’s say that you want to search the Contacts database for a friend’s email address.

You ask the content resolver to look for the address. The content resolver sends a request to the content provider to search for the email address.

The Android system looks for the correct content provider and sends the request to it.

The provider finds the address and returns it to the content resolver.

And there you have your friend’s email address!

The content resolver includes methods that you use for database queries and transactions. These methods correspond with the methods included in the content provider:

  • query() – to search for data in the database
  • insert() – to add data in the database
  • delete() – to delete data in the database
  • update() – to update data in the database
  • getType() – returns the MIME type of the data in the database

What’s your address?

Content URIs

You use a URI to identify data in a content provider.

This is the address that you pass to the content resolver when you want to access a database created in another app.

Typically you will use the constant CONTENT_URI for the address to the database.

The CONTENT_URI is made up like this:

  • The scheme – content://
  • AUTHORITY – complete address of the provider. Unique for each content provider. Use your package name plus the name of your content provider
  • Path – this is the table name. It’s optional
  • ID – row id. Used to identify a single row. It’s optional

Putting it all together, this is what a CONTENT_URI would look like:


content://com.example.slqitemodule. MyContentProvider/MyContacts_table

You’d use this address to query the whole table

content://com.example.slqitemodule. MyContentProvider/MyContacts_table/12

You’d use this address to query row 12 in the table

Tell the police about your content provider

Declare the provider in the AndroidManifest.xml file

You need to declare your content provider in your manifest file. At a minimum this is what it looks like:

Register content provider in the manifest file

The Android system now includes this provider in its list of Content Providers

Note the following:

  • authorities – consists of the <package name >.<your provider’s name>
  • name – the name of your ContentProvider class

Finding the data

Here’s the procedure:

One app has a database and a registered content provider.

Another app uses a content resolver to request data from a content provider.

The Android system uses the URI to find the correct provider to send the request to.

The content provider uses the URI to find the data and returns it to the content resolver.

Match making: The Uri Matcher

You need to have an address for any data that you want to access in a database. This is commonly known as the CONTENT_URI.

You’d declare the CONTENT_URI in your content provider like this:

Content provider contentUri

Then when making a query you’d pass the CONTENT_URI as the URI for the data that you are querying.

Addressing all the rows of data

Generally, you can use a URI that addresses all the data in the database, in which case you would use the CONTENT_URI as is (without the row ID at the end), like this:

Content://com.example.slqitemodule. MyContentProvider/MyContacts_table

The CONTENT_URI addressing all rows

Addressing a single row of data

If you want to address a specific row of data, you can, by adding the row’s ID to the end of the CONTENT_URI, like this:

Content://com.example.slqitemodule. MyContentProvider/MyContacts_table/12

This identifies the data in row 12

Build your black book of addresses

Basically the uri matcher creates a list of URI’s and matches them to an integer constant. This makes it easier to build the correct query.

Why would you need to do this?

Let’s look at an example:

Content provider uriMatcher

This is our UriMatcher. It matches two addresses

Note the following:

  • SINGLE_ROW – this is the constant that is used when matching a URI for a single row. These are addresses with the row ID on the end
  • ALL_ROWS – this is the constant for the address used to access all the rows
  • “/#” - this is the wildcard representing an integer. It’s used for the row ID
  • “/*” - you could also use this wildcard for text. For example, you could use this to search for a single row where one of the columns matches the string that you supply

Content://com.example.slqitemodule. MyContentProvider/MyContacts_table/”USA”

This is what an address with a text wildcard could look like

UriMatcher adding address

 You would then create another constant say, SINGLE_TEXT_ROW and assign it an integer value of 3

You would then add the address to the matcher like this:

uriMatcher text wildcard

We can add any number of possible Uri’s to the matcher by including the AUTHORITY, a PATH and an integer value.

When a request is made to the content provider, it tries to match the given URI with those in the uri matcher and returns the corresponding integer value.

You can then use the integer value to make it easier to build your queries. Just use a switch statement. Here’s a rough example of how to do it:

UriMatcher switch statement

A simplified version of how you could build your queries using the matcher

Table MIME types

You must include the getType() method in your content provider. This returns the type of data requested by the URI argument.

Content types have a type and a sub-type – type/subtype.

For example, an image could be seen as the type and the specific type of image, png as the sub-type – image/png.

Android accepts two media types for content providers – one for individual items and another for a directory containing many items.

  • Type
    • For single items –
    • For directory –
  • Sub-type – these are all the data types that your provider supports. Its format is vnd.<your company.content type>. In our case it is MyContacts_table

Generally you would use it like this:


getType() returns Android’s vendor-specific MIME format

Using the Content Provider

Creating the Content Provider’s database

The onCreate() method of your content provider is called when your app starts. This initialises your content provider.

Content provider onCreate() method

Starting the content provider creates the database if it doesn’t already exist

Opening the database

Only open the database when you need it.

Closing the database

Leave the content provider open while your app is running.

There is no need to close the database at any time.

The Android system will kill your app and close the database if it needs additional resources.

Interacting with the database

If you’re using a SQLite database then you can use any of the SQLiteDatabase class’s query and transaction methods.

These are the methods you’ll need to include in your content provider:

  • getType() – returns the content providers MIME type
  • query() – returns a Cursor containing the set of required data
  • insert() – adds data to the database
  • delete() – deletes data in the database
  • update() – updates data in the database

The query

The query will return a Cursor object.

These are the general steps to follow:

  • Open the database
  • Create a SQLiteQueryBuilder object
  • Use a switch statement to match the URI
  • Build your query
  • Execute the query
  • Return the cursor

Inserting data

These are the general steps to follow:

  • Open the database
  • Put your data into a ContentValues object
  • Execute the insert
  • Construct the URI of the inserted row
  • Notify observers of modified database
  • Return the URI of the inserted row

Deleting data

These are the general steps to follow:

  • Open the database
  • Use a switch statement to create your selection and selection argument options
  • Execute the delete
  • Notify observers of modified database
  • Return the number of deleted rows

Updating data

These are the general steps to follow:

  • Open the database
  • Put your data into a ContentValues object
  • Use a switch statement to create your selection and selection argument options
  • Execute the update
  • Notify observers of modified database
  • Return the number of rows updated

I’ll show you how we use these methods when we work through an example in a later tutorial.

You need to use a Content Resolver to access the database from another app

The content resolver has the same methods.

Apps wanting to access the database would use their content resolver’s methods.

The content resolver would then pass the request to the other app's content provider. The provider would then return the result.

You can still use the SQLiteDatabase methods to access the database

You can still use the SQLiteDatabase methods without using a content resolver to query and modify the database if you wish. But you can only do this from within the app that created the database. See the Using a SQLite database in Android tutorial. 

I hope that you have found this tutorial helpful. 

You'll probably also be interested in the next tutorial in the series, Creating our Custom Content Provider: Part 1. Building the provider.

Please consider subscribing to our notification email. We’ll send you one email on Friday with links to our latest tutorials. That way you won’t miss out. If we didn’t publish any then we won’t send any email. No spam. 

This tutorial was created using Android Studio. You can download the project files here  File download icon 

Are you using Eclipse or another IDE? Here's how you can use this project's Android Studio files.