Examples and features of cross-process communication methods in Android (2): ContentProvider
1. Introduction to ContentProvider
In Android, some data (such as Address Book, audio, and video files) is used by many applications. In order to better provide external data, the Android system provides the Content Provider for us to access the data mentioned above. For example, the Content Provider function is used for many scanning functions in the music player (of course, some players implement the underlying functions by themselves ). The advantage is unified management. For example, if an audio file is added, the underlying layer will notify the Content Provider of this change, so that the application can obtain the latest data when it accesses it.
Of course, Android also allows us to define our own Content Provider, as long as we inherit its base class and implement the following method.
Public boolean onCreate () is called when ContentProvider is created
Public Cursor query (Uri, String [], String, String [], String): Used to query the ContentProvider of a specified Uri. A Cursor
Public Uri insert (Uri, ContentValues): add data to ContentProvider Based on the specified Uri
Public int update (Uri, ContentValues, String, String []): Used to update data in the ContentProvider of the specified Uri
Public int delete (Uri, String, String []): deletes the specified data according to the Uri.
Public String getType (Uri): the MIME type used to return the data in the specified Uri.
* If the operated data belongs to the set type, the MIME-type string should start with vnd. android. cursor. dir.
For example, if the Uri of all p1 records is content: // contacts/p1, the returned MIME-type string is "vnd. android. cursor. dir/p1 ".
* If the data to be operated belongs to a non-set type, the MIME-type string should start with vnd. android. cursor. item.
For example, if the Uri of the student record whose id is 100 is content: // contacts/student/100, the returned MIME type string should be "vnd. android. cursor. item/student ".
2. Uri Introduction
A standard Uri is content: // authority/path, which can be divided into the following three parts:
(1) content: //: This part is specified by ContentProvider, just as http: // represents the Http protocol. The ContentProvider protocol is content ://
(2) authorities: It must be unique in the Android system, because the system uses it to determine which ContentProvider to operate or access, this must be the same as the web site on the Internet.
(3) path: Resource path.
Obviously, from the above analysis, it can be seen that although ContentProvider can also implement cross-process communication, its applicable scenarios are mainly related to databases, and sometimes it may also be storage methods such as text files or XML files.
3. ContentResolver
It makes no sense to define a ContentProvider, because ContentProvider is only a content provider and is valuable only when it is read by other applications (processes. The following describes how to use ContentResolver to implement ContentProvder:
GetContentResolver (): Provided by the Context class, used to obtain the ContentResolver object;
Insert (Uri uri, ContentValues values): insert values data to the ContentProvider corresponding to the Uri;
Update (Uri uri, ContentValues values, String where, String [] selectionArgs): update the data at where in the ContentProvider corresponding to the Uri, where selectionArgs is the filter parameter;
Query (Uri uri, String [] projection, String selection, String [] selectionArgs, String sortOrder): query the data at the where position in the ContentProvider corresponding to the Uri, where selectionArgs is the filter parameter, sortOrder is the sorting method;
Delete (Uri uri, String where, String [] selectionArgs): delete the data at the where in the ContentProvider corresponding to the Uri. selectionArgs is the filter parameter;
4. UriMatcher
To determine the actually processed Uri of a ContentProvider and determine the data operated by the Uri parameter in each method, the Android system provides the UriMatcher tool class. It mainly has the following two methods:
(1) void addURI (String authority, String path, String code): This method is used to register a Uri with the UriMatcher object. The authority and path are combined into a Uri, and the code indicates the ID code corresponding to the Uri;
(2) int match (Uri uri): Judge the ID code of the specified Uri based on the previously registered Uri. If no matching ID is found,-1 is returned for this method.
The following describes the usage of ContentProvider through two instances. The first instance defines a ContentProvider and reads it from another application. The second instance reads contacts from the current mobile phone.
The first example is the project structure shown in:
The following is the code of each class. The first is the definition of constants:
Package com. android. student. utils; import android.net. uri; /*** the ContentProvider-related strings and the fields in the data table corresponding to Student * @ author Bettar **/public class StudentWords {// note that the authorities attribute in the Manifest file must be consistent this is consistent. Public static final String AUTHORITY = "com. android. student. provider "; public static final Uri STUDENT_WITH_ID_URI = Uri. parse ("content: //" + AUTHORITY + "/student"); public static final Uri STUDENT_URI = Uri. parse ("content: //" + AUTHORITY + "/student"); public static final String TABLE_NAME = "student"; public static final String ID = "id "; public static final String NAME = "name"; public static final String SCORE = "score"; public static final String ADDR = "address ";}
Then there is the Database Help class:
Import com. android. student. utils. studentWords; import android. content. context; import android. database. sqlite. SQLiteDatabase; import android. database. sqlite. SQLiteOpenHelper; import android. widget. toast; public class StudentDbHelper extends SQLiteOpenHelper {private Context context; public StudentDbHelper (Context context, String name, int version) {super (context, name, null, version); this. context = context ;}@ Overridepublic void onCreate (SQLiteDatabase db) {String createSQL = "create table" + StudentWords. TABLE_NAME + "(" + StudentWords. ID + "integer primary key autoincrement," + StudentWords. NAME + "varchar," + StudentWords. SCORE + "integer," + StudentWords. ADDR + "varchar)" mongodb.exe cSQL (createSQL) ;}@ Overridepublic void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion) {// when upgrading the version, you may want to modify the table structure. Here, you do not need to consider the upgrade problem, so you only need to use Toast to prompt Toast. makeText (context, "newVersion:" + newVersion + "will replace oldVersion:" + oldVersion, Toast. LENGTH_LONG ). show ();}}
Finally, the definition of the ContentProvider class is as follows:
Package com. android. student. provider; import com. android. student. database. studentDbHelper; import android. content. contentProvider; import android. content. contentUris; import android. content. contentValues; import android. content. uriMatcher; import android. database. cursor; import android. database. sqlite. SQLiteDatabase; import android.net. uri; import android. provider. userDictionary. words; import com. android. stu Dent. utils. studentWords; public class StudentProvider extends ContentProvider {private static final String TAG = "StudentProvider"; private static UriMatcher matcher = new UriMatcher (UriMatcher. NO_MATCH); private static final int STUDENT_WITH_ID = 1; private static final int STUDENT = 2; private StudentDbHelper dbHelper; static {matcher. addURI (StudentWords. AUTHORITY, "student/#", STUDENT_WITH_ID); // matcher. ad DURI (StudentWords. AUTHORITY, "student", SINGLE_STUDENT); // note that # Is the wildcard matcher. addURI (StudentWords. AUTHORITY, "student", STUDENT) ;}@ Override public boolean onCreate () {dbHelper = new StudentDbHelper (this. getContext (), "student. db3 ", 1); return true ;}@ Override public String getType (Uri uri) {switch (matcher. match (uri) {case STUDENT_WITH_ID: return "vnd. android. cursor. item/com. android. student "; ca Se STUDENT: return "vnd. android. cursor. dir/com. android. student "; default: throw new IllegalArgumentException (" Unknown Uri: "+ uri );}} /*** combine a Single selection Filter condition into a complex filtering condition containing the id * @ param uri * @ param selection * @ return */private String getComplexSelection (Uri uri, string selection) {long id = ContentUris. parseId (uri); String complexSelection = StudentWords. ID + "=" + id; if (selection! = Null &&! "". Equals (selection) {complexSelection + = "and" + selection;} return complexSelection ;}@ Overridepublic int delete (Uri uri, String selection, String [] selectionArgs) {SQLiteDatabase db = dbHelper. getReadableDatabase (); int num = 0; switch (matcher. match (uri) {case STUDENT_WITH_ID: String complexSelection = getComplexSelection (uri, selection); num = db. delete (StudentWords. TABLE_NAME, complexSelection, selectionArg S); break; case STUDENT: num = db. delete (StudentWords. TABLE_NAME, selection, selectionArgs); break; default: throw new IllegalArgumentException ("Unknown Uri:" + uri);} // The Notification data has changed getContext (). getContentResolver (). policychange (uri, null); return num;} @ Overridepublic Uri insert (Uri uri, ContentValues values) {SQLiteDatabase db = dbHelper. getReadableDatabase (); switch (matcher. match (uri) {case STUDENT_WITH_ID: case STU DENT: long rowId = db. insert (StudentWords. TABLE_NAME, StudentWords. ID, values); if (rowId> 0) {Uri studentUri = ContentUris. withAppendedId (uri, rowId); // If the observer is set, notify all the observer getContext (). getContentResolver (). categorychange (studentUri, null); return studentUri;} break; default: throw new IllegalArgumentException ("Unknow Uri:" + uri);} return null ;} /*** note that the projection is actually columns, that is, the column name array */@ Overridepublic Cursor query (Ur I uri, String [] projection, String selection, String [] selectionArgs, String sortOrder) {SQLiteDatabase db = dbHelper. getReadableDatabase (); switch (matcher. match (uri) {// This actually contains the id information. case STUDENT_WITH_ID: String complexSelection = getComplexSelection (uri, selection); return db. query (StudentWords. TABLE_NAME, projection, complexSelection, selectionArgs, null, null, sortOrder); // This is not a number, but it may not be multiple. One can be used. Case STUDENT: return db. query (StudentWords. TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder); default: throw new IllegalArgumentException ("Unknow Uri" + uri); }}@ Overridepublic int update (Uri uri, contentValues values, String selection, String [] selectionArgs) {SQLiteDatabase db = dbHelper. getWritableDatabase (); int num = 0; switch (matcher. match (uri) {case STUDENT_WITH_ID: String complexSelection = getComplexSelection (uri, selection); num = db. update (StudentWords. TABLE_NAME, values, complexSelection, selectionArgs); break; case STUDENT: num = db. update (StudentWords. TABLE_NAME, values, selection, selectionArgs); break; default: throw new IllegalArgumentException ("Unknow Uri:" + uri);} getContext (). getContentResolver (). categorychange (uri, null); return num ;}}
Of course, remember to add the ContentProvider declaration to the Manifest file:
The following is an example of ContentResolver. The file structure in the project is as follows:
Then the layout file:
<喎?"http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4KPHByZSBjbGFzcz0 = "brush: java;"> The StudentWords class also exists in the project. Because it is exactly the same as the StudentWords above, it is not listed here. The MainActivity code is as follows:
Package com. android. student. studentcontentresolver; import java. util. arrayList; import java. util. list; import java. util. map; import com. android. student. utils. studentWords; import android.net. uri; import android. OS. bundle; import android. app. activity; import android. content. contentResolver; import android. content. contentUris; import android. content. contentValues; import android. database. cursor; import android. v Iew. menu; import android. widget. button; import android. widget. editText; import android. widget. toast; import android. view. view; public class MainActivity extends Activity implements View. onClickListener {ContentResolver contentResolver; private EditText nameET, scoreET, addressET; private Button insertButton; private EditText inputNameET; private Button searchButton; private EditText inputIdForUpdateET, inputIdF OrDeleteET; private Button updateButton, deleteButton; private void initView () {nameET = (EditText) findViewById (R. id. nameET); scoreET = (EditText) findViewById (R. id. scoreET); addressET = (EditText) findViewById (R. id. addrET); insertButton = (Button) findViewById (R. id. insertButton); inputNameET = (EditText) findViewById (R. id. inputNameET); searchButton = (Button) findViewById (R. id. searchButton); inputIdForUpdateET = (EditText) fi NdViewById (R. id. inputIdET); inputIdForDeleteET = (EditText) findViewById (R. id. inputIdForDeleteET); updateButton = (Button) findViewById (R. id. updateButton); deleteButton = (Button) findViewById (R. id. deleteButton); insertButton. setOnClickListener (this); searchButton. setOnClickListener (this); updateButton. setOnClickListener (this); deleteButton. setOnClickListener (this) ;}@ Overrideprotected void onCreate (Bundle savedIn StanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); contentResolver = getContentResolver (); initView () ;}@ Overridepublic void onClick (View view) {switch (view. getId () {case R. id. insertButton: insert (); break; case R. id. searchButton: query (); break; case R. id. updateButton: update (); break; case R. id. deleteButton: delete (); break; default: break;} private void insert () {String name = n AmeET. getText (). toString (); String score = scoreET. getText (). toString (); String addr = addressET. getText (). toString (); ContentValues values = new ContentValues (); values. put (StudentWords. NAME, name); values. put (StudentWords. SCORE, new Integer (score); values. put (StudentWords. ADDR, addr); // contentResolver. insert (StudentWords. SINGLE_STUDENT_URI, values); // one is a special case, so use MANY_STUDENTS_URI here. ContentResolver. insert (StudentWords. STUDENT_URI, values); Toast. makeText (getBaseContext (), "student information added", Toast. LENGTH_SHORT ). show ();} private void query () {String name = inputNameET. getText (). toString (); // Cursor cursor = contentResolver. query (uri, projection, selection, selectionArgs, sortOrder) Cursor cursor = contentResolver. query (StudentWords. STUDENT_URI, null, "name like? Or address like? ", New String [] {" % "+ name +" % "," % "+ name +" % "}, null); Toast. makeText (getBaseContext (), getResult (cursor), Toast. LENGTH_LONG ). show ();} private void update () {// Uri updateUri = StudentWords. SINGLE_STUDENT_URI // record whose id value is updated to id Integer id = new Integer (inputIdForUpdateET. getText (). toString (); Uri updateUri = ContentUris. withAppendedId (StudentWords. STUDENT_WITH_ID_URI, id); ContentValues values = new ContentValues (); values. put (StudentWords. NAME, "VictorWang"); contentResolver. update (updateUri, values, null, null);} private void delete () {// delete the record whose id value is id Integer id = new Integer (inputIdForDeleteET. getText (). toString (); Uri deleteUri = ContentUris. withAppendedId (StudentWords. STUDENT_WITH_ID_URI, id); contentResolver. delete (deleteUri, null, null);} private List
ConvertCursor2List (Cursor cursor) {List
Result = new ArrayList
(); While (cursor. moveToNext () {result. add (cursor. getString (1) + ""); result. add (cursor. getString (2) + ""); result. add (cursor. getString (3) + "");} return result;} private String getResult (Cursor cursor) {StringBuilder sb = new StringBuilder (); while (cursor. moveToNext () {sb. append (cursor. getString (1) + ""); sb. append (cursor. getString (2) + ""); sb. append (cursor. getString (3) + "\ n");} return sb. toString () ;}@ Overridepublic boolean onCreateOptionsMenu (Menu menu) {// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater (). inflate (R. menu. main, menu); return true ;}}
The running result is as follows:
Write it here today. The contact person and the ContentObserver example will be added later.