Creating the Content Provider

1. First open the Earthquake project and create a new EarthquakeProvider class that extends ContentProvider. Include stubs to override the onCreate, getType, query, insert, delete, and update methods.

package com.paad.earthquake;

import android.content.*;

import android.database.Cursor;

import android.database.SQLException;

import android.database.sqlite.SQLiteOpenHelper;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteQueryBuilder;

import android.net.Uri;

import android.text.TextUtils;

import android.util.Log;

public class EarthquakeProvider extends ContentProvider { ©Override public boolean onCreate() { }

©Override public String getType(Uri url) { }

©Override public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs, String sort) {

©Override public Uri insert(Uri _url, ContentValues _initialValues) { }

©Override public int delete(Uri url, String where, String[] whereArgs) { }

©Override public int update(Uri url, ContentValues values, String where, String[]wArgs) {

2. Publish the URI for this provider. This URI will be used to access this Content Provider from within other application components via the ContentResolver.

public static final Uri CONTENT_URI =

Uri.parse("content://com.paad.provider.earthquake/earthquakes");

3. Create the database that will be used to store the earthquakes. Within the EarthquakeProvider create a new SQLiteDatabase instance and expose public variables that describe the column names and indexes. Include an extension of SQLiteOpenHelper to manage database creation and version control.

// The underlying database private SQLiteDatabase earthquakeDB;

private static final String TAG = "EarthquakeProvider"; private static final String DATABASE_NAME = "earthquakes.db"; private static final int DATABASE_VERSION = 1; private static final String EARTHQUAKE_TABLE = "earthquakes";

// Column Names public static final String KEY_ID = "_id"; public static final String KEY_DATE = "date"; public static final String KEY_DETAILS = "details"; public static final String KEY_LOCATION_LAT = "latitude"; public static final String KEY_LOCATION_LNG = "longitude"; public static final String KEY_MAGNITUDE = "magnitude"; public static final String KEY_LINK = "link";

// Column indexes public static final int DATE_COLUMN = 1; public static final int DETAILS_COLUMN = 2; public static final int LONGITUDE_COLUMN = 3; public static final int LATITUDE_COLUMN = 4; public static final int MAGNITUDE_COLUMN = 5; public static final int LINK_COLUMN = 6;

// Helper class for opening, creating, and managing database version control private static class earthquakeDatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_CREATE = "create table " + EARTHQUAKE_TABLE + " (" + KEY_ID + " integer primary key autoincrement, " + KEY_DATE + " INTEGER, " + KEY_DETAILS + " TEXT, " + KEY_LOCATION_LAT + " FLOAT, " + KEY_LOCATION_LNG + " FLOAT, " + KEY_MAGNITUDE + " FLOAT), " + KEY_LINK + " TEXT);";

public earthquakeDatabaseHelper(Context context, String name,

CursorFactory factory, int version) { super(context, name, factory, version);

©Override public void onCreate(SQLiteDatabase db) { db.execSQL(DATABASE_CREATE);

©Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion + ", which will destroy all old data");

db.execSQL("DROP TABLE IF EXISTS " + EARTHQUAKE_TABLE); onCreate(db);

4. Create a UriMatcher to handle requests using different URIs. Include support for queries and transactions over the entire dataset (quakes) and a single record matching a quake index value (quake_id).

Prepared for ASHLEE KABAT, email: [email protected] Order number: 56760408 This PDF is for the purchaser's personal use in accordance with the Wrox Terms of Service and under US copyright as stated on this book's copyright page. If you did not purchase this copy, please visit www.wrox.com to purchase your own copy.

// Create the constants used to differentiate between the different URI // requests.

private static final int QUAKES = 1; private static final int QUAKE_ID = 2;

private static final UriMatcher uriMatcher;

// Allocate the UriMatcher object, where a URI ending in 'earthquakes' will // correspond to a request for all earthquakes, and 'earthquakes' with a trailing '/[rowlD]' will represent a single earthquake row. static {

uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

uriMatcher.addURI("com.paad.provider.Earthquake", "earthquakes", QUAKES); uriMatcher.addURI("com.paad.provider.Earthquake", "earthquakes/!", QUAKE_ID);

5. Override the getType method to return a string for each of the URI structures supported.

©Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) {

case QUAKES: return "vnd.android.cursor.dir/vnd.paad.earthquake"; case QUAKE_ID: return "vnd.android.cursor.item/vnd.paad.earthquake"; default: throw new IllegalArgumentException("Unsupported URI: " + uri);

6. Override the provider's onCreate handler to create a new instance of the database helper class, and open a connection to the database.

©Override public boolean onCreate() {

Context context = getContext();

earthquakeDatabaseHelper dbHelper = new earthquakeDatabaseHelper(context,

DATABASE_NAME, null, DATABASE_VERSION); earthquakeDB = dbHelper.getWritableDatabase(); return (earthquakeDB == null) ? false : true;

7. Implement the query and transaction stubs. Start with the query method, which should decode the request being made based on the URI (either all content or a single row), and apply the selection, projection, and sort-order criteria parameters to the database before returning a result Cursor.

©Override public Cursor query(Uri uri,

String[] projection, String selection, String[] selectionArgs, String sort) {

SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

qb.setTables(EARTHQUAKE_TABLE);

Prepared for ASHLEE KABAT, email: [email protected] Order number: 56760408 This PDF is for the purchaser's personal use in accordance with the Wrox Terms of Service and under US copyright as stated on this book's copyright page. If you did not purchase this copy, please visit www.wrox.com to purchase your own copy.

// If this is a row query, limit the result set to the passed in row. switch (uriMatcher.match(uri)) {

case QUAKE_ID: qb.appendWhere(KEY_ID + "=" + uri.getPathSegments().get(1)); break;

default : break;

// If no sort order is specified sort by date / time String orderBy;

if (TextUtils.isEmpty(sort)) {

orderBy = sort;

// Apply the query to the underlying database. Cursor c = qb.query(earthquakeDB, projection, selection, selectionArgs, null, null, orderBy);

// Register the contexts ContentResolver to be notified if // the cursor result set changes.

c.setNotificationUri(getContext().getContentResolver(), uri);

// Return a cursor to the query result. return c;

8. Now implement methods for inserting, deleting, and updating content. In this case the process is an exercise in mapping Content Provider transaction requests to their database equivalents.

©Override public Uri insert(Uri _uri, ContentValues _initialValues) { // Insert the new row, will return the row number if // successful.

long rowID = earthquakeDB.insert(EARTHQUAKE_TABLE, "quake", _initialValues);

// Return a URI to the newly inserted row on success, if (rowID >0) {

Uri uri = ContentUris.withAppendedId(CONTENT_URI, rowID); getContext().getContentResolver().notifyChange(uri, null); return uri;

throw new SQLException("Failed to insert row into " + _uri);

©Override public int delete(Uri uri, String where, String[] whereArgs) { int count;

switch (uriMatcher.match(uri)) { case QUAKES:

count = earthquakeDB.delete(EARTHQUAKE_TABLE, where, whereArgs); break;

case QUAKE_ID:

String segment = uri.getPathSegments().get(1); count = earthquakeDB.delete(EARTHQUAKE_TABLE, KEY_ID + "="

+ segment

+ (¡TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);

break;

default: throw new IllegalArgumentException("Unsupported URI: " + uri);

getContext().getContentResolver().notifyChange(uri, null); return count;

©Override public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { int count;

switch (uriMatcher.match(uri)) {

case QUAKES: count = earthquakeDB.update(EARTHQUAKE_TABLE, values, where, whereArgs);

break;

case QUAKE_ID: String segment = uri.getPathSegments().get(1);

count = earthquakeDB.update(EARTHQUAKE_TABLE, values, KEY_ID + "=" + segment

+ (¡TextUtils.isEmpty(where) ? " AND (" + where + ')' : ""), whereArgs);

break;

default: throw new IllegalArgumentException("Unknown URI " + uri);

getContext().getContentResolver().notifyChange(uri, null); return count;

9. With the Content Provider complete, register it in the manifest by creating a new <provider> node within the application tag.

<provider android:name=".EarthquakeProvider"

android:authorities="com.paad.provider.earthquake" />

All code snippets in this example are part of the Chapter 7 Todo List 2 project, available for download at Wrox.com.

Mobile Apps Made Easy

Mobile Apps Made Easy

Quick start guide to skyrocket your offline and online business success with mobile apps. If you know anything about mobile devices, you’ve probably heard that famous phrase coined by one of the mobile device’s most prolific creators proclaiming that there’s an app for pretty much everything.

Get My Free Training Guide


Post a comment