ContentProvider of four Android Components
ContentProviderContentProvider of four Android Components
By default, Android applications cannot obtain data from other applications, which is the cornerstone of Android Security (sandbox principle ). However, we often need to share data with other applications. The content provider is an interface that can share data with other applications.
It can be simply understood that the content provider is a component that can share data between different applications. It is equivalent to a man-in-the-middle who exposes data to the man-in-the-middle, the other one obtains the corresponding data through the intermediary.
The following picture can be displayed more intuitively:
ContentProvider
IngetContext
AndAndroidTestCast
IngetContext
The method is the same. It is a simulated context and can be called only after the class is initialized.setContext
Methodcontext
Set to record in your member variables,
ThereforegetContext
It can only be placed in the method, not in the member location, because it is null on the member, and the class will have been initialized in the method call.
ContentProvider
Inquery()
The database cannot be closed because other applications callquery
You must continue to use the return value when using this method.Cursor
So you cannot close the database becauseCursor
It cannot be used,
Cursor
The stored data is actually a reference of the database.Cursor
You cannot find the data in it,Cursor.close()
Only resources used by Cursor are released. Here is a majority of words.
According to Dianne Hackborn (Android framework engineer) there is no need to close the database in a content provider.
It is assumed that the content provider is loaded when the process is started and will always exist after the process is destroyed.
When resources are released, the database is closed.
If the data isSQLiteDatabase
, The table must have_id
Is used to indicate the uniqueness of each record.
Inheritance
ContentProvider
And implement the corresponding method.
Public class NoteProvider extends ContentProvider {private static final int NOTES = 1; private static final int NOTE_ID = 2; public static final String AUTHORITY = com. charon. demo. provider. noteprovider; public static final String TABLE_NAME = note; // to define a name named 'content _ URI ', you must specify a unique String value for it, the best solution is to use the full name of the class public static final Uri CONTENT_URI = Uri. parse (content: // + AUTHORITY +/+ TABLE_NAME); // declare a path Checker, the returned value when the parameter is Uri does not match // although it is a man-in-the-middle, no one wants data. Therefore, check that only the persons that meet our requirements are required, we will give him data. Private static UriMatcher sUriMatcher = new UriMatcher (UriMatcher. NO_MATCH); private NoteSQLiteOpenHelper mSQLiteOpenHelper; private SQLiteDatabase mSQLiteDatabase; static {// create matching rules. For example, the found path is ccom. charon. demo. provider. noteprovider/note/1 indicates sUriMatcher to operate the record with id 1 in the note table. addURI (AUTHORITY, TABLE_NAME, NOTES); sUriMatcher. addURI (AUTHORITY, TABLE_NAME +/#, NOTE_ID);}/*** Implement this to initialize your content provider on startup. * This method is called for all registered content providers on the * application main thread at application launch time. it must not perform * lengthy operations, or application startup will be delayed. *
*
You should defer nontrivial initialization (such as opening, * upgrading, and scanning databases) until the content provider is used * (via {@link #query}, {@link #insert}, etc). Deferred initialization * keeps application startup fast, avoids unnecessary work if the provider * turns out not to be needed, and stops database errors (such as a full * disk) from halting application launch. *
*
If you use SQLite, {@ link android. database. sqlite. SQLiteOpenHelper} * is a helpful utility class that makes it easy to manage databases, * and will automatically defer opening until first use. if you do use * SQLiteOpenHelper, make sure to avoid calling * {@ link android. database. sqlite. SQLiteOpenHelper # getReadableDatabase} or * {@ link android. database. sqlite. SQLiteOpenHelper # getWritableDatabase }* From this method. (Instead, override * {@ link android. database. sqlite. SQLiteOpenHelper # onOpen} to initialize the * database when it is first opened .) ** @ return true if the provider was successfully loaded, false otherwise */@ Override public boolean onCreate () {mSQLiteOpenHelper = new NoteSQLiteOpenHelper (getContext (); return true ;} /*** query method exposed by the content provider. * // @ Override public Cursor query (Uri ur I, String [] projection, String selection, String [] selectionArgs, String sortOrder) {mSQLiteDatabase = mSQLiteOpenHelper. getReadableDatabase (); Cursor cursor; // 1. the important thing is to check the uri path. switch (sUriMatcher. match (uri) {case NOTES: break; case NOTE_ID: String id = uri. getLastPathSegment (); if (TextUtils. isEmpty (selection) {selection = selection + _ id = + id;} else {selection = selection + and + _ Id = + id;} break; default: throw new IllegalArgumentException (UnKnown Uri + uri); break;} cursor = mSQLiteDatabase. query (TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); if (cursor! = Null) {cursor. setNotificationUri (getContext (). getContentResolver (), uri);} return cursor;}/*** Implement this to handle requests for the MIME type of the data at the * given URI. the returned MIME type shoshould start *vnd.android.cursor.item
For a single record, * orvnd.android.cursor.dir/
For multiple items. * This method can be called from multiple threads, as described in * Processes * and Threads .*
*
Note that there are no permissions needed for an application to * access this information; if your content provider requires read and/or * write permissions, or is not exported, all applications can still call * this method regardless of their access permissions. this allows them * to retrieve the MIME type for a URI when dispatching intents. ** @ param uri the URI to query. * @ return a MIME type string, or {@ code null} if there is no type. * // @ Override public String getType (Uri uri) {// The comment is clear. The following is a common format // The IMEI type vnd of a single record. android. cursor. item/vnd. . // IMEI type vnd. android. cursor. dir/vnd. . Switch (sUriMatcher. match (uri) {case NOTE_ID: // If the uri is content: // com. charon. demo. noteprovider/note/1 return vnd. android. cursor. item/vnd. charon. note; case NOTES: return vnd. android. cursor. dir/vnd. charon. note; default: return null;} // This MIME type is used to match AndroidManifest. under the xml file tag Tag sub-tag Android: mimeType. // If they are inconsistent, the corresponding Activity cannot be started.} @ Override public Uri insert (Uri uri, ContentValues values) {mSQLiteDatabase = mSQLiteOpenHelper. getWritableDatabase (); switch (sUriMatcher. match (uri) {case NOTES: break; case NOTE_ID: break; default: throw new IllegalArgumentException (UnKnown Uri + uri); break;} long rowId = mSQLiteDatabase. insert (TABLE_NAME, null, values); if (rowId> 0) {Uri noteUri = ContentUris. withAppendedId (CONTENT_URI, rowId); getContext (). getContentResolver (). policychange (noteUri, null); return noteUri;} return null;} @ Override public int delete (Uri uri, String selection, String [] selectionArgs) {mSQLiteDatabase = mSQLiteOpenHelper. getWritableDatabase (); switch (sUriMatcher. match (uri) {case NOTES: break; case NOTE_ID: String id = uri. getLastPathSegment (); if (TextUtils. isEmpty (selection) {selection = selection + _ id = + id;} else {selection = selection + and + _ id = + id;} break; default: throw new IllegalArgumentException (UnKnown Uri + uri); break;} int count = mSQLiteDatabase. delete (TABLE_NAME, selection, selectionArgs); getContext (). getContentResolver (). policychange (uri, null); return count ;}@ Override public int update (Uri uri, ContentValues values, String selection, String [] selectionArgs) {switch (sUriMatcher. match (uri) {case NOTES: break; case NOTE_ID: break; default: throw new IllegalArgumentException (UnKnown Uri + uri); break;} mSQLiteDatabase = mSQLiteOpenHelper. getWritableDatabase (); int update = mSQLiteDatabase. update (TABLE_NAME, values, selection, selectionArgs); return update ;}
Register in the inventory file and specify its authorities
Use the content provider to obtain data.
ContentResolver
Proceed
ContentProvider
,
ContentResolver
Used for management
ContentProvider
Instance, and you can find the specified
ContentProvider
And get the data in it.
Java
Public void query (View view ){
// Obtain the content provider's parser intermediary
ContentResolver resolver = getContentResolver ();
Cursor cursor = resolver. query (NoteProvider. CONTENT_URI, null );
While (cursor. moveToNext ()){
String name = cursor. getString (cursor. getColumnIndex (name ));
Int id = cursor. getInt (cursor. getColumnIndex (id ));
Float money = cursor. getFloat (cursor. getColumnIndex (money ));
System. out. println (id = + id +, name = + name +, money = + money );
}
Cursor. close ();
}
Public void insert (View view ){
ContentResolver resolver = getContentResolver ();
ContentValues values = new ContentValues ();
Values. put (name, buy shampoo );
Values. put (money, 22.58f );
Resolver. insert (NoteProvider. CONTENT_URI, values );
}
Public void update (View view ){
ContentResolver resolver = getContentResolver ();
ContentValues values = new ContentValues ();
Values. put (name, buy shampoo );
Values. put (money, 42.58f );
Resolver. update (NoteProvider. CONTENT_URI, values, name = ?, New String [] {buy shampoo paste });
}
Public void delete (View view ){
ContentResolver resolver = getContentResolver ();
Resolver. delete (NoteProvider. CONTENT_URI, name = ?, New String [] {buy shampoo paste });
}
Content observer
Principle of content observer:
How a content provider actually stores its data under the covers is up to its designer. But all content providers implement a common interface for querying the provider and
returning results — as well as for adding, altering, and deleting data.
It's an interface that clients use indirectly, most generally through ContentResolver objects.
You get a ContentResolver by calling getContentResolver() from within the implementation of an Activity or other application component:
You can then use the ContentResolver's methods to interact with whatever content providers you're interested in.
One Party uses content observer to observe changes
Protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); ContentResolver resolver = getContentResolver (); resolver. registerContentObserver (NoteProvider. CONTENT_URI, true, new NoteObserver (new Handler ();} private class NoteObserver extends ContentObserver {public NoteObserver (Handler handler) {super (handler );} // when the data changes, the onchange method is executed. @ Override public void onChange (boolean selfChange) {super. onChange (selfChange); Log. I (TAG, new text messages are generated ...); // 1. use the content provider intermediary to obtain the user's text message data. contentResolver resolver = getContentResolver ();//.. re-query cursor = ...; cursor. close ();}}
One Party sends the changed message when the change occurs.
This step is implemented internally by some system content providers. If you want to expose your own programs, you must add this code.
getContext().getContentResolver().notifyChange(uri, null);