Create a gist now

Instantly share code, notes, and snippets.

Despicable & Minion Content Provider for Android
package com.sergiandreplace.content;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.SparseArray;
/**
* This class is responsible to manage all minions
*/
public abstract class DespicableContentProvider extends ContentProvider {
protected static final String CONTENT = "content://";
public static final String CONTENT_TYPE_DIR = "vnd.android.cursor.dir/vnd.";
public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.";
SparseArray<MinionContentProvider> minions;
int minionId = 0;
private UriMatcher uriMatcher;
private boolean minionsRecruited = false;
@Override
public boolean onCreate() {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
minions = new SparseArray<MinionContentProvider>();
return false;
}
/**
* This method is a placeholder to perform all the addMinion calls in order
* to setup our army of minions. It will be invoked on the first use of the
* minions
*/
public abstract void recruitMinions();
/**
* Current Authority for this content provider. Must be the same than the
* one declared in the manifest
*
* @return The Authority value
*/
public abstract String getAuthority();
/**
* Adds a minion to the list of minions that will answer to data requests
*
* @param minion
* The minion to add
* @return The identifier of the minion
*/
public int addMinion(MinionContentProvider minion) {
minionId++;
uriMatcher.addURI(getAuthority(), minion.getBasePath(), minionId);
minions.put(minionId, minion);
minion.setContext(getContext());
return minionId;
}
/**
* Retrieves the minion that answers to the provided uri It will also invoke
* the recruitMinions method if they have not been recruited before
*
* @param uri
* A data uri
* @return The minion who requested the type of uri provided
*/
private MinionContentProvider getMinion(Uri uri) {
if (!minionsRecruited) {
recruitMinions();
minionsRecruited = true;
}
int uriType = uriMatcher.match(uri);
if (uriType == -1) {
throw new IllegalArgumentException("Unknown URI: " + uri);
}
return minions.get(uriType);
}
/**
* Getter for the current database
*
* @return returns the database used by the content provider
*/
public abstract SQLiteDatabase getDb();
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
MinionContentProvider minion = getMinion(uri);
Cursor cursor = minion.query(getDb(), uri, projection, selection, selectionArgs, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor;
}
@Override
public String getType(Uri uri) {
MinionContentProvider minion = getMinion(uri);
return minion.getType();
}
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
MinionContentProvider minion = getMinion(uri);
long id = minion.insert(getDb(), uri, contentValues);
getContext().getContentResolver().notifyChange(uri, null);
return Uri.parse(minion.getBasePath() + "/" + id);
}
@Override
public int delete(Uri uri, String where, String[] selectionArgs) {
MinionContentProvider minion = getMinion(uri);
int rowsDeleted = minion.delete(getDb(), uri, where, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return rowsDeleted;
}
@Override
public int update(Uri uri, ContentValues values, String where, String[] selectionArgs) {
MinionContentProvider minion = getMinion(uri);
int rowsUpdated = minion.update(getDb(), uri, values, where, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null);
return rowsUpdated;
}
@Override
public int bulkInsert(Uri uri, ContentValues[] valuesTable) {
MinionContentProvider minion = getMinion(uri);
SQLiteDatabase db = getDb();
db.beginTransaction();
for (ContentValues values : valuesTable) {
minion.insert(db, uri, values);
}
db.setTransactionSuccessful();
db.endTransaction();
getContext().getContentResolver().notifyChange(uri, null);
return valuesTable.length;
}
}
package com.sergiandreplace.content;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import java.util.Arrays;
import java.util.HashSet;
/**
* This class manage a specific provider
*/
public abstract class MinionContentProvider {
private Context context;
/**
* Returns the impl path of this entity. For example "sports". Will be added to the getAuthority of the DespicableContentProvider
* in the shape content://{DespicableContentProvider.getAuthority()}/{getBasePath()}
* @return The impl path
*/
public abstract String getBasePath();
/**
* Performs a query on the entity managed by this minion
* @param db the current db
* @param uri The URI to query. This will be the full URI sent by the client; if the client is requesting a specific record, the URI will end in a record number that the implementation should parse and add to a WHERE or HAVING clause, specifying that _id value.
* @param projection The list of columns to put into the cursor. If null all columns are included.
* @param selection A selection criteria to apply when filtering rows. If null then all rows are included.
* @param selectionArgs You may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.
* @paramsortOrder How the rows in the cursor should be sorted. If null then the provider is free to define the sort order.
* @return a Cursor or null.
*/
public abstract Cursor query(SQLiteDatabase db, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
/**
* Inserts value in the entity managed by this minion
* @param db the current db
* @param uri The content:// URI of the insertion request.
* @param contentValues A set of column_name/value pairs to add to the database.
* @return The URI for the newly inserted item.
*/
public abstract long insert(SQLiteDatabase db, Uri uri, ContentValues contentValues);
/**
* Deletes one or more rows for the entity managed by this minion
* @param db
* @param uri The full URI to query, including a row ID (if a specific record is requested).
* @param where An optional restriction to apply to rows when deleting.
* @param selectionArgs the values for the arguments
* @return The number of rows affected.
*/
public abstract int delete(SQLiteDatabase db, Uri uri, String where, String[] selectionArgs);
/**
* Updates one or more rows
* @param uri The URI to query. This can potentially have a record ID if this is an update request for a specific record.
* @param values A Bundle mapping from column names to new column values (NULL is a
* valid value).
* @param where An optional filter to match rows to update.
* @return the number of rows affected.
* @return
*/
public abstract int update(SQLiteDatabase db, Uri uri, ContentValues values, String where, String[] selectionArgs);
public abstract String getType();
public void setContext(Context context) {
this.context=context;
}
public Context getContext() {
return context;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment