Use of Content Observer in Android

Keywords: Android Database Java SDK


Reproduced from: http://blog.csdn.net/qinjuning

Preface: In work, you need to open a thread to query a large number of one data base The value sent a change, resulting in a large overhead, and later under the guidance of the boss, the use of

ContentObserver solved the problem perfectly and was very excited. After that, I also summarized the ContentObserver.

 

Content Observer - Content Observer, which is designed to observe (capture) specific Uri-induced data base Change, and then do some corresponding processing, it is similar to

Trigger in database technology triggers when the Uri observed by ContentObserver changes. Triggers are divided into table triggers and row triggers.

Accordingly, ContentObserver is also divided into "Table ContentObserver" and "Row" ContentObserver, which is related to the Uri MIME Type it monitors.

 

Familiar with Content Provider, you should know that we can register different types of Uri through the UriMatcher class, and we can use these different types of Uri.

Uri queries for different results. According to the results returned by Uri, Uri Type can be divided into Uri that returns multiple data and Uri that returns single data.

 

 

Register/unregister the ContentObserver method, and the method prototype in the abstract class ContentResolver is as follows:

 

    public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)

Function: Register a ContentObserver derived class instance for the specified Uri and call back the instance object to process when the given Uri changes.

Parameter: uri) Uri that needs to be observed (registration in UriMatcher, otherwise the Uri is meaningless)

Notfy ForDescendents represents an exact match for false, that is, only the Uri is matched.

For true, it means that it can match its derived Uri at the same time. Examples are as follows:

Assume that Uri registered in UriMatcher has one type:

content://com.qin.cb/student

                                2 ,content://com.qin.cb/student/# 

Content://com.qin.cb/student/schoolchild

 

Assume that the Uri we need to observe is content://com.qin.cb/student, and if there is a change in data, the Uri is content://com.qin.cb/student.

content://com.qin.cb/student/schoolchild, when notify ForDescendents is false, the ContentObserver will not listen.

However, when notify ForDescendents is ture, it can capture the database changes of the Uri.

 

Derived class instance of ContentObserver

 

 

    public final void  unregisterContentObserver(ContentObserver observer)

Function: Cancel observation of a given Uri

Parameter: Derived class instance of observer ContentObserver

 

        

Introduction to ContentObserver Class

 

Construction method public void ContentObserver(Handler handler)  

Description: All derived classes of ContentObserver need to call this constructor

Parameters:handler Handler object. It could be the main thread Handler (at which point the UI can be updated) It can also be any Handler object.

Common methods

   void onChange(boolean selfChange)

Function: Callback the method to process the observed Uri changes. All derived classes of ContentObserver need to overload the method to process the logic.

Parameter: After selfChange callback, its value is generally false, which means little (I don't know, understanding the method is the most important).

 

The other two methods are not very useful, and I don't understand them either. You can understand them by referring to SDK, presumptuously.

  boolean  deliverSelfNotifications()

Note: Returns true if this observer is interested in notifications for changes made through the cursor the observer is registered with.

  

  final void dispatchChange(boolean selfChange)

 

 

The steps to observe a particular Uri are as follows:

 

Create our specificContentObserver Derived classes must overload the parent construction method and onChange() method to handle the function implementation after callback

2. Use context.getContentResolover() to get the ContentResolove object, and then call registerContentObserver() method to register the content observer.

3. Because the life cycle of ContentObserver is not synchronized with Activity and Service, manual calls are required when not needed.

unregisterContentObserver() to cancel registration.    

 

 

 

Okay, here's the basic explanation. A brief description of the small DEMO is given below.

There are two different ContentObserver derived classes in Demo, as follows:

1. Used to observe whether the system has changedFlight mode status

PS: You can go to the SDK to see this type: Android provider.Settings.System. This class encapsulates access to all values under the settings module, such as:

Flight mode status, Bluetooth status, screen brightness values, etc., and the corresponding Uri is provided.

2. The short message data of the observation system has changed. When monitoring the change of short message data, query all sent short messages and display them.

 

There are several types of Uri for short messages:

content://sms/inbox Inbox
Content://sms/send) has been sent
Draft content://sms/draft)
content://sms/outbox Outbox Outbox (message being sent)
content://sms/failed Send Failure
content://sms/queued (e.g. when flying mode is turned on, the text message is in the waiting list)

 

For more information about SMS, you can refer to this blog:< android Medium Management Short Message>

 

When the flight mode is turned on and the text message is sent (note: use the Home key to exit, not the Back key), the DMEO screenshot is as follows:

 

               

 

The DEMO file is as follows:

1. ContentObserver derived from observing flight mode status, AirplaneContentObserver. Java

              

[java] view plain copy

 print?


  1. package com.qin.contentobserver;  
  2.   
  3. import android.content.Context;  
  4. import android.database.ContentObserver;  
  5. import android.net.Uri;  
  6. import android.os.Handler;  
  7. import android.provider.*;  
  8. import android.provider.Settings.SettingNotFoundException;  
  9. import android.util.Log;  
  10.   
  11.   
  12. //Used to observe whether the row of flight mode in the system table has changed, the "row" content observer  
  13. public class AirplaneContentObserver extends ContentObserver {  
  14.   
  15.     private static String TAG = "AirplaneContentObserver" ;  
  16.       
  17.     private static int MSG_AIRPLANE = 1 ;  
  18.       
  19.     private Context mContext;      
  20.     private Handler mHandler ;  //This Handler is used to update UI threads  
  21.       
  22.     public AirplaneContentObserver(Context context, Handler handler) {  
  23.         super(handler);  
  24.         mContext = context;  
  25.         mHandler = handler ;  
  26.     }  
  27.   
  28.     /** 
  29.      * This method is called back when the monitored Uri changes 
  30.      *  
  31.      * @param selfChange This value does not make much sense. Normally, the callback value is false. 
  32.      */  
  33.     @Override  
  34.     public void onChange(boolean selfChange) {  
  35.         Log.i(TAG, "————-the airplane mode has changed————-");  
  36.           
  37.         //Is the system in flight mode?  
  38.         try {  
  39.             int isAirplaneOpen = Settings.System.getInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON);  
  40.             Log.i(TAG, " isAirplaneOpen —–> " +isAirplaneOpen) ;  
  41.             mHandler.obtainMessage(MSG_AIRPLANE,isAirplaneOpen).sendToTarget() ;  
  42.         }  
  43.         catch (SettingNotFoundException e) {  
  44.             // TODO Auto-generated catch block  
  45.             e.printStackTrace();  
  46.         }  
  47.   
  48.     }  
  49.   
  50. }  

 

        

2. ContentObserver derived class, SMS ContentObserver, which observes the database changes of short messages in the system. Java

  

[java] view plain copy

 print?


  1. package com.qin.contentobserver;  
  2.   
  3. import android.content.Context;  
  4. import android.database.ContentObserver;  
  5. import android.database.Cursor;  
  6. import android.net.Uri;  
  7. import android.os.Handler;  
  8. import android.util.Log;  
  9.   
  10.   
  11. //Content Observer Derivative Class is triggered by the Content Observer Content Observer as long as the information database changes.  
  12. public class SMSContentObserver extends ContentObserver {  
  13.     private static String TAG = "SMSContentObserver";  
  14.       
  15.     private int MSG_OUTBOXCONTENT = 2 ;  
  16.       
  17.     private Context mContext  ;  
  18.     private Handler mHandler ;   //Update UI threads  
  19.       
  20.     public SMSContentObserver(Context context,Handler handler) {  
  21.         super(handler);  
  22.         mContext = context ;  
  23.         mHandler = handler ;  
  24.     }  
  25.     /** 
  26.      * This method is called back when the monitored Uri changes 
  27.      *  
  28.      * @param selfChange  This value does not make much sense. Normally, the callback value is false. 
  29.      */  
  30.     @Override  
  31.     public void onChange(boolean selfChange){  
  32.         Log.i(TAG, "the sms table has changed");  
  33.           
  34.         //Query the contents of the inbox.  
  35.         Uri outSMSUri = Uri.parse("content://sms/sent") ;  
  36.           
  37.         Cursor c = mContext.getContentResolver().query(outSMSUri, nullnullnull,"date desc");  
  38.         if(c != null){  
  39.               
  40.             Log.i(TAG, "the number of send is"+c.getCount()) ;  
  41.               
  42.             StringBuilder sb = new StringBuilder() ;  
  43.             //Cyclic traversal  
  44.             while(c.moveToNext()){  
  45. //sb.append("Sender's mobile phone number:" +c. getInt (c. getColumn Index ("address")))  
  46. //Appnd ("Information Content:" +c. getInt (c. getColumn Index ("body")))  
  47. //Appnd ("Check it or not"+c.getInt (c.getColumn Index ("read")))  
  48. //Appnd ("Delivery time:"+c. getInt (c. getColumn Index ("date")))  
  49. //                .append("\n");  
  50.                 sb.append("Sender's cell phone number: "+c.getInt(c.getColumnIndex("address")))  
  51.                   .append("information content: "+c.getString(c.getColumnIndex("body")))  
  52.                   .append("\n");  
  53.             }  
  54.             c.close();            
  55.             mHandler.obtainMessage(MSG_OUTBOXCONTENT, sb.toString()).sendToTarget();          
  56.         }  
  57.     }  
  58.       
  59. }  


3. The main engineering logic is MainActivity.java. Uri, the observation of short messages, passes through test I found that only this Uri could be monitored. "Content://sms" (equivalent to "content://sms/"), but can not listen to other Uri, such as "content://sms/outbox" and so on.

 

[java] view plain copy

 print?


  1. package com.qin.contentobserver;  
  2.   
  3. import android.app.Activity;  
  4. import android.database.Cursor;  
  5. import android.net.Uri;  
  6. import android.os.Bundle;  
  7. import android.os.Handler;  
  8. import android.os.Message;  
  9. import android.provider.*;  
  10. import android.util.Log;  
  11. import android.widget.EditText;  
  12. import android.widget.TextView;  
  13.   
  14. public class MainActivity extends Activity {  
  15.   
  16.     private TextView tvAirplane;  
  17.     private EditText etSmsoutbox;  
  18.   
  19.     //Message type value  
  20.     private static final int MSG_AIRPLANE = 1;  
  21.     private static final int MSG_OUTBOXCONTENT = 2;  
  22.   
  23.     private AirplaneContentObserver airplaneCO;  
  24.     private SMSContentObserver smsContentObserver;  
  25.   
  26.     /** Called when the activity is first created. */  
  27.     @Override  
  28.     public void onCreate(Bundle savedInstanceState) {  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.main);  
  31.   
  32.         tvAirplane = (TextView) findViewById(R.id.tvAirplane);  
  33.         etSmsoutbox = (EditText) findViewById(R.id.smsoutboxContent);  
  34.   
  35.         //Create two objects  
  36.         airplaneCO = new AirplaneContentObserver(this, mHandler);  
  37.         smsContentObserver = new SMSContentObserver(this, mHandler);  
  38.           
  39.         //Registered Content Observer  
  40.         registerContentObservers() ;  
  41.     }  
  42.   
  43.     private void registerContentObservers() {  
  44.         //Get the Uri of the row of "flight mode" in the system table by calling getUriFor method  
  45.         Uri airplaneUri = Settings.System.getUriFor(Settings.System.AIRPLANE_MODE_ON);  
  46.         //Registered Content Observer  
  47.         getContentResolver().registerContentObserver(airplaneUri, false, airplaneCO);  
  48.         //” Table "Content observer, through testing I found that only this Uri -> content://sms can be monitored  
  49.         //You can't listen to other Uri, such as content://sms/outbox  
  50.         Uri smsUri = Uri.parse("content://sms");  
  51.         getContentResolver().registerContentObserver(smsUri, true,smsContentObserver);  
  52.     }  
  53.   
  54.     private Handler mHandler = new Handler() {  
  55.   
  56.         public void handleMessage(Message msg) {  
  57.               
  58.             System.out.println("—mHanlder—-");  
  59.             switch (msg.what) {  
  60.             case MSG_AIRPLANE:  
  61.                 int isAirplaneOpen = (Integer) msg.obj;  
  62.                 if (isAirplaneOpen != 0)  
  63.                     tvAirplane.setText("Flight mode turned on");  
  64.                 else if (isAirplaneOpen == 0)  
  65.                     tvAirplane.setText("Flight mode closed");  
  66.                 break;  
  67.             case MSG_OUTBOXCONTENT:  
  68.                 String outbox = (String) msg.obj;  
  69.                 etSmsoutbox.setText(outbox);  
  70.                 break;  
  71.             default:  
  72.                 break;  
  73.             }  
  74.         }  
  75.     };  
  76. }  


 

On this basis, you can use ContentObserver to achieve SMS blacklisting and smuggling skills, specific reference to this blog:

                <Accept SMS with a specified number>

 

Summary: There are two main cases of using ContentObserver:

1. It is not economical and time-consuming to use threads to operate a database or data that needs frequent detection.

2. Do some things to the database without the user's knowledge, such as sending information quietly, refusing to accept short message blacklist, etc.

 

In both cases, using ContentObserver is undoubtedly the best edge.

 

The code download address is: http://download.csdn.net/detail/qinjuning/3896987

 



     ///////////////////////////////////////////////////////////////////////////////////////

// Important Supplement - > Description of ContentObserver Monitoring Principle

    ///////////////////////////////////////////////////////////////////////////////////////  


Update (2012-05-4, today I gave the framework of ContentProvider a walk, add the following knowledge points):


Why do data changes call back to ContentObserver? Why did our custom ContentProvider data source change?

Later, no response was monitored. ? This is related to the system's callback system logic.

 

After each ContentProvider data source changes, if you want to notify its listener, such as ContentObserver, you must have its corresponding method update / 

When insert / delete, the call this.getContentReslover (). notifychange(uri) is displayed Null method, callback listens for processing logic. Otherwise, we

Content Observer does not monitor data changes. Specific principles, you can refer to Lao Luo's article:

                     <Android Application Component Content Provider's Shared Data Update Notification Mechanism

   

PS: Lao Luo's analysis of ContentProvider's principle is still very powerful. We can take a look at the old Luo series carefully and follow the source code carefully.



Additionally, it is strongly recommended that the content Observer object be constructed by passing the Hadler where the main thread is located, as follows:

 

[java] view plain copy

 print?


  1. airplaneCO = new AirplaneContentObserver(this, mHandler); //mHandler is a Handler object for UI threads  

Otherwise, an exception may be reported when updating the UI (Security Exception when a non-UI thread updates the UI). System-level processes can lead to

Restart your cell phone. Or in the onChange() method, use the Handler class correlation method to call back to the UI thread to update the UI view.


Posted by ruach on Fri, 12 Apr 2019 18:30:34 -0700