Free Android app covering all aspects of addiction, including prevention and treatment

Creating our Custom Content Provider: Part 1. Building the provider

  • Written by  Clive

Building the Content Provider

This is part 1 of creating our custom content provider. This is where we build our ContentProvider class.

Building iconIn part 2, we'll show how we use the provider within the same app to access the database.

The parts making up the content provider

Here’s an app that uses a content provider to make its database available for use by other apps.

We’ll work through it and you’ll see how easy it is to create a custom content provider.

Screenshot of the Custom Content Provider

A screenshot of the MainActivity

Here are the files that we will need:

Content Provider files needed

The basic files

The Constants: MyDbContractConstants

This file has all the constants, such as the:

  • Database name
  • Database table name
  • Database version
  • Database column titles

We covered this in the Using a sqlite database in Android tutorial

The Helper: MyDbOpenHelper

This is our SQLiteOpenHelper class. It creates, opens and updates the database.

We also covered this in the Using a sqlite database in Android tutorial

MyContentProvider: Our ContentProvider class

This is our ContentProvider class. It contains everything needed for our content provider.

Content Provider class

Our content provider extends the ContentProvider class

We include a number of constants which we use to make up the database’s address.

CONTENT_URI is the constant that we use for the address to access the database. You can read more about this in the tutorial, Android Content Providers

The ContentProvider class – this is what creates the content provider. Things that happen in this class:

  • onCreate() – this method is called when your app starts. It initialises the content provider
  • uriMatcher – basically a list of possible Uri’s, each assigned an integer value. The integer enables you to use a switch statement to filter the query Uri and build your query statement
  • database interaction methods. These methods are used to query and modify the database
    • getType() – returns the database MIME type
    • query() – used to get data out of the database. Returns a Cursor containing the requested data
    • insert() – inserts data into the database
    • delete() – deletes data in the database
    • update() – updates data in the database

Our openDatabase method

We create a SQLiteDatabase object, database and then create our SQLiteOpenHelper, databaseHelper:

Open database

Our openDatabase() method first tries to open a writable database. If this fails, we open a readable database

The onCreate() method creates the provider when the app starts. It executes on the main thread so don’t include any time consuming tasks here.

The Content Provider's onCreate method

The content provider is initialised when the app starts

Let’s look at the query and transaction methods in more detail.

Remember that these methods are called by the corresponding content resolver methods. The results are returned to the content resolver.

The query

The query searches the database for data matching the requirements sent by the content resolver. The result is returned in a Cursor.

Content Provider query() method

The query

 

Note the following:

  • openDatabase() – this calls our openDatabase() method. It first tries to open a writable database. A readable database is opened if this fails
  • groupBy – a parameter passed to the query() method. It filters how the rows should be grouped. We pass null so that the rows will not be grouped. You can change this to suite your needs
  • having - a parameter passed to the query() method. Filters which row groups to be included in the Cursor. Must be null if groupBy is null. This will include all row groups
  • SQLiteQueryBuilder – a class that makes building SQL queries easy
  • setTables – sets the database table to be used for this query
  • switch – used to filter the Uri of the received query. In this case, we filter the address for a single item and build the query accordingly
    • rowId – this is the ID of the row of data that is being queried. It is the last path segment in the received Uri address
    • uri.getPathSegments().get(1) – gets the ID from the uri path segment
    • appendWhere() – this appends the requested row id to the WHERE clause of the SQL query. The query will search the KEY_ID column for an ID matching the requested row id
  • queryBuilder.query() – this is the query that does the work, searches the database and returns the result. It is passed a number of parameters (from the content resolver):
    • database – the database to query
    • projection –a String[] - these are the column values to be returned
    • selection – a String – it’s the WHERE clause in this format: column_name = ?
    • selectionArguments – a String[] – these are the arguments for the selection wildcard (?)
    • sortOrder – a String – whether the results should be ordered (in alphabetical order for example)
    • cursor.setNotificationUri() - pass the query Uri here. This will ensure that Observers will be notified that the database has been modified. Open cursors will be refreshed
    • return cursor – the cursor is returned to the content resolver

getType()

This returns the content provider’s MIME type. See the Android Content Provider tutorial for more on this.

The insert()

This inserts a row of data into the database. It returns the Uri of the inserted row.

Content Provider insert() method

The insert

Note the following:

  • openDatabase() – opens a writeable database
  • nullColumnHack – must be null if you’re adding data. See the tutorial, Using a SQLite database in Android if you want to insert an empty row
  • database.insert() – this inserts the row of data into the database and returns the row ID or -1 if there was a problem. It has a number of parameters:
    • the database table name
    • nullColumnHack
    • contentValues – these are the values that need to be inserted into the database. A contentValues object stores the data in key/value pairs. The key would be the column name and the value the information to insert into that column
    • if statement – this checks the returned value of the insert. If it’s greater than -1 then the insert was a success. We now need to:
      • build a Uri for the inserted row – we use ContentUris.withAppendedId() to append the inserted row id to the BASE_URI
      • notify any registered observers that we have changed a row of data so that they can update any open cursors. This will ensure that the latest data is available. We use notifyChange() to do this. Note that the Uri passed here is the Uri that will be monitored. Passing CONTENT_URI ensures that ALL inserts will be monitored
  • returns the Uri of the inserted row or null if there was a problem

The delete()

This deletes a row or rows of data and returns the number of rows deleted.

Content provider delete

The delete

Note the following:

  • openDatabase() – opens a writeable database
  • switch – we don’t use the switch statement here but you can if you need to
  • selection – a String – the WHERE clause in this format: column_name = ? Pass null to delete all rows. This results in the delete() method not returning a count for the number of rows deleted. If you want a count then you need to pass 1 for the selection string
  • database.delete() – this deletes the row or rows. It has a number of parameters:
    • the database table name
    • selection – a String – the WHERE clause in this format: column_name = ?
    • selectionArguments – a String[] – these are the arguments for the selection wildcard (?)
  • notifyChange() - notify any registered observers that we have changed the contents of the database so that they can update any open cursors. This will ensure that the latest data is available. We use notifyChange() to do this
  • return deleteCount – returns the number of rows deleted

The update()

Updates a row or rows in the database. Returns the number of rows updated.

Content provider update

The update

Note the following:

  • openDatabase() – opens a writeable database
  • switch – use the switch statement to filter the Uri. If the uriMatcher matches a single row then:
    • getPathSegments().get(1) - get the row id from the Uri
    • selection – limit the selection to the specified row
  • database.update() – performs the update. It receives a number of parameters:
    • the database table name
    • contentValues – these are the values to replace the existing values for the specified row/s
    • selection – a String – the WHERE clause in this format: column_name = ?
    • selectionArguments – a String[] – these are the arguments for the selection wildcard (?)
  • notifyChange() - notify any registered observers that we have changed the contents of the database so that they can update any open cursors. This will ensure that the latest data is available. We use notifyChange() to do this
  • return numberRowsUpdated – returns the number of rows updated

I hope that you have found this tutorial helpful. 

Have a look at Part 2 where we see how to use the provider, Creating our Custom Content Provider: Part 2. Using the provider. You may also be interested in this tutorial on using Loaders to get the data out of the database.  

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.