SoFunction
Updated on 2025-03-11

Simple examples of using custom ContentProvider and ContentObserver in Android

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:

&lt;RelativeLayout  
  xmlns:andro 
  xmlns:tools="/tools" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" 
  &gt; 
 
   &lt;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" 
  /&gt; 
 
&lt;/RelativeLayout&gt; 



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&gt;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 &lt; 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&lt;=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:

&lt;RelativeLayout xmlns:andro 
  xmlns:tools="/tools" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" &gt; 
 
  &lt;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" /&gt; 
   
   &lt;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" /&gt; 
   
 
  &lt;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" /&gt; 
 
  &lt;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" /&gt; 
 
  
   &lt;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" /&gt; 
 
&lt;/RelativeLayout&gt; 

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!