Android App Development - 10 Content providers

download Android App Development - 10 Content providers

If you can't read please download the document

Transcript of Android App Development - 10 Content providers

  1. 1. Content Providers
  2. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 22. Content Providers To allow other applications access to the Content Provider you must specify required permissions in the Manifest file. Creation - Permission