2. Content Providers A Content Provider is a main component
that manages access to a centralized repository of data. The main
purpose is to share data with other applications (then communicates
data in interprocess communication). It is used to create a
database for internal research application. A Content Provider
manages a SQLite DB. There are default Content Providers in the
system to access common data: Dictionary Contacts SMS Calls ...
Content Provider
3. Content Providers A Content Provider is accessed through a
client object called ContentResolver that enables interprocess
Communication. For access to any Content Provider the application
must specify its permissions in the Manifest file. Typically
permissions are divided into Reading permissions Writing
permissions When you ask permission in writing is not necessary to
require reading ones. Ex. To request permission to read the user
dictionary, you must add permission request in the Manifest file
and you can not request access at runtime: Access
4. Content Providers To perform a query on a ContentProvider
you can use ContentResolver.query() method to get the Cursor to
read: // Queries the user dictionary and returns results mCursor =
getContentResolver().query( mUri, // The content URI of the words
table mProjection, // The columns to return for each row
mSelectionClause // Selection criteria mSelectionArgs, // Selection
criteria mSortOrder); // The sort order for the returned rows
Parameters: Uri: Table name Projection: String array to specify
what columns to invlude in the query result Selection: string that
specifies selection criteria SelectionArgs: argument strings for
selection SortOrder: order of the query result Query
5. Content Providers The table identifying Uri is composed by:
Prefix: "content:// Authority: it identifies the Provider Path: it
identifies the table using its name Es.
content://user_dictionary/words To create the Uri, use utility
class called Uri, Uri.Builder and ContentUris that simplify the
management of Uri and provide access to a single row of the table
with the static method ContentUris.withAppendedId() Uri singleUri =
ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);
Query - Uri
6. Content Providers To construct a SQL query you must follow
its syntax String[] mSelectionArgs = {""}; mSearchString =
mSearchWord.getText().toString(); if
(TextUtils.isEmpty(mSearchString)) { mSelectionClause = null;
mSelectionArgs[0] = ""; } else { mSelectionClause =
UserDictionary.Words.WORD + " = ?"; mSelectionArgs[0] =
mSearchString; } mCursor = getContentResolver().query(
UserDictionary.Words.CONTENT_URI, mProjection, mSelectionClause
mSelectionArgs, MsortOrder); SELECT _ID, word, locale FROM words
WHERE word = ORDER BY word ASC; Query - Statement
7. Content Providers The "?" in selectionClause and
selectionArgs are useful to protect the DB from unknowing
operations like dropthe user would insert. Ex. String
mSelectionClause = "var = " + mUserInput; The user would insert
"nothing: DROP TABLE *;". Instead the following is used to avoid
problema: String mSelectionClause = "var = ?"; String[]
selectionArgs = {""}; selectionArgs[0] = mUserInput; Query -
Statement
8. Content Providers The ContentResolver.query() method returns
a Cursor that contains all the rows resulting from the query with
the specified columns from the projection. For this reason, you
must iterate over the lines and you can retrieve the value for each
column. if(mCursor!=null){ while(mCursor.moveToNext()){
mCursor.getBlob(mCursor.getColumnIndex(BLOB_COLUMN_NAME));
mCursor.getDouble(mCursor.getColumnIndex(DOUBLE_COLUMN_NAME));
mCursor.getFloat(mCursor.getColumnIndex(FLOAT_COLUMN_NAME));
mCursor.getInt(mCursor.getColumnIndex(INT_COLUMN_NAME));
mCursor.getLong(mCursor.getColumnIndex(LONG_COLUMN_NAME));
mCursor.getShort(mCursor.getColumnIndex(SHORT_COLUMN_NAME));
mCursor.getString(mCursor.getColumnIndex(STRING_COLUMN_NAME)); }
}else{ //... } Query - Cursor
9. Content Providers ContentResolver.insert() method inserts a
new rowin the provider table and returns the created Uri.
content://user_dictionary/words/ The insertion takes place via a
contentValues object that contains the values of the new row. You
do not need to manage _ID because it is handled automatically. To
insert a null value use ContentValues.putNull(). Uri mNewUri;
ContentValues mNewValues = new ContentValues();
mNewValues.put(UserDictionary.Words.APP_ID, "example.user");
mNewValues.put(UserDictionary.Words.LOCALE, "en_US");
mNewValues.put(UserDictionary.Words.WORD, "insert");
mNewValues.put(UserDictionary.Words.FREQUENCY, "100"); mNewUri =
getContentResolver().insert( UserDictionary.Word.CONTENT_URI,// the
user dictionary content URI mNewValues // the values to insert );
String mSelectionClause = "var = ?"; String[] selectionArgs = {""};
selectionArgs[0] = mUserInput; Insert
10. Content Providers The method ContentResolver.update()
updates the rows resulting from the query with the values specified
by contentValues. ContentValues mUpdateValues = new
ContentValues(); String mSelectionClause =
UserDictionary.Words.LOCALE + "LIKE ?"; String[] mSelectionArgs =
{"en_%"}; int mRowsUpdated = 0;
mUpdateValues.putNull(UserDictionary.Words.LOCALE); mRowsUpdated =
getContentResolver().update( UserDictionary.Words.CONTENT_URI,//
the user dictionary content URI mUpdateValues // the columns to
update mSelectionClause // the column to select on mSelectionArgs
// the value to compare to ); Update
11. Content Providers The method ContentResolver.delete()
delete query resulting rows. String mSelectionClause =
UserDictionary.Words.APP_ID + " LIKE ?"; String[] mSelectionArgs =
{"user"}; int mRowsDeleted = 0; mRowsDeleted =
getContentResolver().delete( UserDictionary.Words.CONTENT_URI,//
the user dictionary content URI mSelectionClause // the column to
select on mSelectionArgs // the value to compare to ); Delete
12. Content Providers A ContentProvider is necessary only if:
You need to share data with other applications You want to develop
a custom search system for autocomplete text In all other cases a
Database SQLite is sufficient to achieve the purpose. Creation -
Analysis
13. Content Providers To configure a Content Provider you must
establish its Authority and the Path of its tables. Authority: to
avoid conflicts extend the application package to make it unique
Path: to define tables path extend Authority:
com.example..provider/table1 com.example..provider/table2 ...
Creation - Design
14. Content Providers When a ContentProvider receives a Uri it
must understand what action to take. Use a UriMatcher that maps Uri
to integers. public class ExampleProvider extends ContentProvider {
private static final UriMatcher sUriMatcher; static {
sUriMatcher.addURI("com.example.app.provider", "table3", 1);
sUriMatcher.addURI("com.example.app.provider", "table3/#", 2); }
@Override public Cursor query(Uri uri, String[] projection, String
selection, String[] selectionArgs, String sortOrder) { switch
(sUriMatcher.match(uri)) { // If the incoming URI was for all of
table3 case 1: if (TextUtils.isEmpty(sortOrder)) sortOrder = "_ID
ASC"; break; // If the incoming URI was for a single row case 2:
selection = selection + "_ID = " + uri.getLastPathSegment(); break;
default: // If the URI is not recognized, you should do some error
handling here. } // call the code to actually do the query } }
Creation - Design
15. Content Providers The abstract class ContentProvider must
manage accesses to data by calls from a ContentResolver from other
processes and/or applications. The methods to implement are:
ContentProvider.query() ContentProvider.insert()
ContentProvider.update() ContentProvider.delete()
ContentProvider.getType() ContentProvider.onCreate() These methods
have the same signature as the ContentResolver ones to simplify
their use. Creation - Implementation
16. Content Providers Using a SQLite Database simply return the
Cursor returned by SQLiteDatabase.query() @Override public Cursor
query(Uri uri, String[] projection, String selection, String[]
selectionArgs, String sortOrder) { SQLiteQueryBuilder queryBuilder
= new SQLiteQueryBuilder(); queryBuilder.setTables(TABLE); int
uriType = sURIMatcher.match(uri); switch (uriType) { case 1:
queryBuilder.appendWhere(Contract._ID + "=" +
uri.getLastPathSegment()); break; case 2: break; default: throw new
IllegalArgumentException("Unknown URI"); } Cursor cursor =
queryBuilder.query(database, projection, selection, selectionArgs,
groupBy, having, sortOrder);
cursor.setNotificationUri(getContext().getContentResolver(), uri);
return cursor; } Creation Implementation - query()
17. Content Providers @Override public Uri insert(Uri uri,
ContentValues values) { int uriType = sURIMatcher.match(uri); long
id; switch (uriType) { case 1: id = database.insert(TABLE_NAME,
null, values); break; default: throw new
IllegalArgumentException("Unknown URI: " + uri); }
getContext().getContentResolver().notifyChange(uri, null); return
ContentUris.withAppendedId(Contract.CONTENT_URI, id); } Creation
Implementation - insert()
18. Content Providers @Override public int delete(Uri uri,
String selection, String[] selectionArgs) { int rowsDeleted =
database.delete(TABLE_NAME, selection, selectionArgs);
getContext().getContentResolver().notifyChange(uri, null); return
rowsDeleted; } Creation Implementation - delete()
19. Content Providers @Override public int update(Uri uri,
ContentValues values, String selection, String[] selectionArgs) {
int rowsUpdated = 0; int uriType = sURIMatcher.match(uri); switch
(uriType) { case 1: rowsUpdated = database.update(TABLE_NAME,
values, selection, selectionArgs); break; default: throw new
IllegalArgumentException("Unknown URI: " + uri); }
getContext().getContentResolver().notifyChange(uri, null); return
rowsUpdated; } Creation Implementation - update()
20. Content Providers @Override public boolean onCreate() {
dbHelper = new DatabaseHelper(getContext()); database =
dbHelper.getWritableDatabase(); return database != null; }
protected static final class DatabaseHelper extends
SQLiteOpenHelper { private static final String DBNAME = "db_name";
private static final String SQL_CREATE = "CREATE TABLE " + "main (
_ID INTEGER PRIMARY KEY, WORD TEXT, FREQUENCY INTEGER, LOCALE TEXT
)"; public WeatherDatabaseHelper(Context context) { super(context,
DBNAME, null, 1); } public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE); } @Override public void
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db); } }
Creation Implementation - onCreate()
21. Content Providers The method returns a string in MIME
format that describes the type of data returned by the Uri
argument. In the case of the SQLite Database, string is composed in
this way: Type: vnd Subtype: Single row: android.cursor.item/
Multiple rows: android.cursor.dir/ Provider: vnd.. @Override public
String getType(Uri uri) { switch (sURIMatcher.match(uri)){ case 1:
return "vnd.android.cursor.dir/vnd.com.example.provider"; case 2:
return "vnd.android.cursor.item/vnd.com.example.provider"; default:
throw new IllegalArgumentException("Unsupported URI: " + uri); } }
Creation Implementation - getType()
22. Content Providers To allow other applications access to the
Content Provider you must specify required permissions in the
Manifest file. Creation - Permission