Simple examples of using custom ContentProvider and ContentObserver in Android
Example description:
There are two projects in this example. One of the projects completed the custom ContentProvider, and the other project was used to test the custom ContentProvider and used ContentObserver to listen for data changes in the custom ContentProvider in the project.
The following code is the project TestContentProvider
ContentProviderTest is as follows:
package ; import ; import ; import ; import ; import ; import ; import ; /** * Demo description: * Implementation of custom ContentProvider * ContentProvider is mainly used to share data between different applications, which is also the official recommended method. * * Notes: * 1 Properties when registering ContentProvider in * android:exported="true" means that other applications are allowed to access. * 2 Note the role of the two symbols * and # in Uri * where * means matching characters of any length * Where # represents data matching any length * so: * A Uri that can match all tables can be written as: * content:///* * A Uri that can match any row in the person table can be written as: * content:///person/# * */ public class ContentProviderTest extends ContentProvider { private SQLiteDatabaseOpenHelper mSQLiteDatabaseOpenHelper; private final static String AUTHORITY=""; private static UriMatcher mUriMatcher; private static final int PERSON_DIR = 0; private static final int PERSON = 1; /** * Initialize UriMatcher with static code blocks * The UriMatcher contains multiple Uri, each Uri represents an operation * When the (Uri uri) method is called, the corresponding code of the uri will be returned; * For example, PERSONS and PERSON here */ static { mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); // This URI means that all persons are returned, where PERSONS is the identification code of the specific Uri (AUTHORITY, "person", PERSON_DIR); // This URI means returning a person, where PERSON is the identification code of the specific Uri (AUTHORITY, "person/#", PERSON); } /** * The getType(Uri uri) method must be overridden in the custom ContentProvider. * This method is used to obtain the MIME type corresponding to the Uri object. * * A Uri corresponding MIME string follows the following three points: * 1 Must start with vnd * 2 If the data corresponding to the Uri may contain multiple records, the return string should start with "/" * 3 If the data corresponding to the Uri only contains one record, the return string should start with "/" */ @Override public String getType(Uri uri) { switch ((uri)) { case PERSON_DIR: return "/"+AUTHORITY+".persons"; case PERSON: return "/"+AUTHORITY+".person"; default: throw new IllegalArgumentException("unknown uri"+()); } } @Override public boolean onCreate() { mSQLiteDatabaseOpenHelper=new SQLiteDatabaseOpenHelper(getContext()); return true; } /** * Insert operation: * There is only one possibility for inserting: insert into a table * The result is the Uri corresponding to the new record * Method() returns the result as the primary key value corresponding to the new record */ @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = (); switch ((uri)) { case PERSON_DIR: long newId = ("person", "name,phone,salary", values); //Notify the outside world that the data in the ContentProvider has changed so that ContentObserver can make corresponding getContext().getContentResolver().notifyChange(uri, null); return (uri, newId); default: throw new IllegalArgumentException("unknown uri" + ()); } } /** * Update operation: * There are two possibilities for updating: update a table or update a certain piece of data * When updating a certain piece of data, the principle is similar to querying a certain piece of data, see below. */ @Override public int update(Uri uri, ContentValues values, String selection,String[] selectionArgs) { SQLiteDatabase db = (); int updatedNum = 0; switch ((uri)) { // Update table case PERSON_DIR: updatedNum = ("person", values, selection, selectionArgs); break; // Update a piece of data according to id case PERSON: long id = (uri); String where = "person".equals(())) { where = selection + " and " + where; } updatedNum = ("person", values, where, selectionArgs); break; default: throw new IllegalArgumentException("unknown uri" + ()); } //Notify the outside world that the data in the ContentProvider has changed so that ContentObserver can make corresponding getContext().getContentResolver().notifyChange(uri, null); return updatedNum; } /** * Delete operation: * There are two possibilities for deletion: delete a table or delete a certain piece of data * When deleting a certain piece of data, the principle is similar to querying a certain piece of data, see below. */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = (); int deletedNum = 0; switch ((uri)) { // Delete the table case PERSON_DIR: deletedNum = ("person", selection, selectionArgs); break; // Delete a piece of data according to the id case PERSON: long id = (uri); String where = "person".equals(())) { where = selection + " and " + where; } deletedNum = ("person", where, selectionArgs); break; default: throw new IllegalArgumentException("unknown uri" + ()); } //Notify the outside world that the data in the ContentProvider has changed so that ContentObserver can make corresponding getContext().getContentResolver().notifyChange(uri, null); return deletedNum; } /** * Query operation: * There are two possibilities for querying: querying a table or querying a certain piece of data * * Notes: * Be careful when querying a certain piece of data - because here is querying according to personid * A certain piece of data, but there may be other restrictions. For example: * Require personid is 2 and name is xiaoming1 * So there are two steps when querying: * Step 1: * parse out the personid and put it in the where query conditions * Step 2: * Determine whether there are other restrictions (such as name). If so, group them into where query conditions. * * See below for detailed code. */ @Override public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) { SQLiteDatabase db = (); Cursor cursor =null; switch ((uri)) { // Query table case PERSON_DIR: cursor = ("person", projection, selection, selectionArgs,null, null, sortOrder); break; // Query a piece of data by id case PERSON: // Step 1: long id = (uri); String where = "person".equals(())) { where = selection + " and " + where; } cursor = ("person", projection, where, selectionArgs, null, null, sortOrder); break; default: throw new IllegalArgumentException("unknown uri" + ()); } return cursor; } }
SQLiteDatabaseOpenHelper is as follows:
package ; import ; import ; import ; public class SQLiteDatabaseOpenHelper extends SQLiteOpenHelper { public SQLiteDatabaseOpenHelper(Context context) { super(context, "", null, 1); } @Override public void onCreate(SQLiteDatabase db) { ("create table person(personid integer primary key autoincrement,name varchar(20),phone varchar(12),salary Integer(12))"); } //Call this method when the database version number changes @Override public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) { //("ALTER TABLE person ADD phone varchar(12) NULL"); //("ALTER TABLE person ADD salary Integer NULL"); } } MainActivityas follows: [java] view plain copy package ; import ; import ; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(); } }
as follows:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:andro package="" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /> <uses-permission android:name="" /> <uses-permission android:name=".ACCESS_NETWORK_STATE" /> <uses-permission android:name=".WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name=".MOUNT_UNMOUNT_FILESYSTEMS" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="" android:label="@string/app_name" > <intent-filter> <action android:name="" /> <category android:name="" /> </intent-filter> </activity> <provider android:name="" android:authorities="" android:exported="true" /> </application> </manifest>
as follows:
<RelativeLayout xmlns:andro xmlns:tools="/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="The app contains a custom ContentProvider" android:textSize="15sp" android:layout_centerInParent="true" /> </RelativeLayout>
The following code is the project TestBaidu
MainActivity is as follows:
package ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; import ; /** * Demo description: * Application A (TestBaidu) calls the custom ContentProvider in another application (TestContentProvider), that is: * 1 Customize the use of ContentProvider * 2 Other applications call the ContentProvider * 3 Use of ContentObserver * * Note description: * 1 This example organizes the code based on previous versions * 2 This example integrates the use of ContentObserver based on previous versions * Use ContentObserver to listen to the ContentProvider data changes at any time. * To implement this function, insert(), update(), delete() of the custom ContentProvider needs to be inserted in the custom ContentProvider * Call getContext().getContentResolver().notifyChange(uri, null); * Notify the outside world that the data in the ContentProvider has changed so that ContentObserver can make corresponding * * Test method: * 1 Test the contentProvider's addition, search, deletion and modification in sequence (note this order)!! * 2 Other applications query the data of the ContentProvider * */ public class MainActivity extends Activity { private Button mAddButton; private Button mDeleteButton; private Button mUpdateButton; private Button mQueryButton; private Button mTypeButton; private long lastTime=0; private ContentResolver mContentResolver; private ContentObserverSubClass mContentObserverSubClass; @Override protected void onCreate(Bundle savedInstanceState) { (savedInstanceState); setContentView(); init(); initContentObserver(); } private void init() { mContentResolver=(); mAddButton=(Button) findViewById(); (new ClickListenerImpl()); mDeleteButton=(Button) findViewById(); (new ClickListenerImpl()); mUpdateButton=(Button) findViewById(); (new ClickListenerImpl()); mQueryButton=(Button) findViewById(); (new ClickListenerImpl()); mTypeButton=(Button) findViewById(); (new ClickListenerImpl()); } // Register a ContentObserver for ContentProvider to observe the data changes of the content provider private void initContentObserver() { Uri uri = ("content:///person"); mContentObserverSubClass=new ContentObserverSubClass(new Handler()); ().registerContentObserver(uri, true,mContentObserverSubClass); } @Override protected void onDestroy() { (); if (mContentObserverSubClass!=null) { ().unregisterContentObserver(mContentObserverSubClass); } } // Customize a content observer ContentObserver private class ContentObserverSubClass extends ContentObserver { public ContentObserverSubClass(Handler handler) { super(handler); } //Use timestamps to avoid multiple calls to onChange( ) @Override public void onChange(boolean selfChange) { (selfChange); ("ContentObserver onChange() selfChange="+ selfChange); if (()-lastTime>2000) { ContentResolver resolver = getContentResolver(); Uri uri = ("content:///person"); // Get the latest data Cursor cursor = (uri, null, null, null,"personid desc limit 1"); while (()) { int personid = (("personid")); ("The data in the content provider has changed, and the person time interval of the first data in the data is too short, and this update is ignored"); } } @Override public boolean deliverSelfNotifications() { return true; } } private class ClickListenerImpl implements OnClickListener { @Override public void onClick(View v) { switch (()) { case : Person person = null; for (int i = 0; i < 5; i++) { person = new Person("xiaoming" + i, "9527" + i, (8888 + i)); testInsert(person); } break; case : testDelete(1); break; case : testUpdate(3); break; case : // Query table // queryFromContentProvider(-1); // Query the data with personid=2 testQuery(2); break; case : testType(); break; default: break; } } } private void testInsert(Person person) { ContentValues contentValues=new ContentValues(); ("name", ()); ("phone", ()); ("salary",()); Uri insertUri=("content:///person"); Uri returnUri=(insertUri, contentValues); ("Added data:returnUri="+returnUri); } private void testDelete(int index){ Uri uri=("content:///person/"+(index)); (uri, null, null); } private void testUpdate(int index){ Uri uri=("content:///person/"+(index)); ContentValues values=new ContentValues(); ("name", "hanmeimei"); ("phone", "1234"); ("salary", 333); (uri, values, null, null); } private void testQuery(int index) { Uri uri=null; if (index<=0) { //Query table uri=("content:///person"); } else { //Check a piece of data according to id uri=("content:///person/"+(index)); } //Complied with the above: query table //Cursor cursor= (uri, null, null, null, null); //Complied with the above: query the data with personid=2 //Note: Because name is in the varchar field, it should be written as "name='xiaoming1'" // If written as "name=xiaoming1" to query, an error will be reported Cursor cursor= (uri, null, "name='xiaoming1'", null, null); while(()){ int personid=(("personid")); String name=(("name")); String phone=(("phone")); int salary=(("salary")); ("Query get:person,name="+name+",phone="+phone+",salary="+salary); } (); } private void testType(){ Uri dirUri=("content:///person"); String dirType=(dirUri); ("dirType:"+dirType); Uri itemUri=("content:///person/3"); String itemType=(itemUri); ("itemType:"+itemType); } }
Person is as follows:
package ; public class Person { private Integer id; private String name; private String phone; private Integer salary; public Person(String name, String phone,Integer salary) { = name; = phone; =salary; } public Person(Integer id, String name, String phone,Integer salary) { = id; = name; = phone; =salary; } public Integer getId() { return id; } public void setId(Integer id) { = id; } public String getName() { return name; } public void setName(String name) { = name; } public String getPhone() { return phone; } public void setPhone(String phone) { = phone; } public Integer getSalary() { return salary; } public void setSalary(Integer salary) { = salary; } @Override public String toString() { return "Person [, name=" + name + ", phone=" + phone+ ", salary=" + salary + "]"; } }
as follows:
<RelativeLayout xmlns:andro xmlns:tools="/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="30dip" android:text="Increase" android:textSize="20sp" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="30dip" android:layout_below="@id/addButton" android:text="Query" android:textSize="20sp" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="30dip" android:layout_below="@id/queryButton" android:text="delete" android:textSize="20sp" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="30dip" android:layout_below="@id/deleteButton" android:text="Revise" android:textSize="20sp" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="30dip" android:layout_below="@id/updateButton" android:text="type" android:textSize="20sp" /> </RelativeLayout>
If you have any questions, please leave a message or go to the community of this site to exchange and discuss. Thank you for reading. I hope it can help you. Thank you for your support for this site!