target
- Master the creation method of content providers and be able to create content providers independently
- Master the steps of using content providers to access other applications, and be able to read the mobile phone address book
- Master the use of content observers, and be able to use content observers to observe the data changes of other programs
In Chapter 5 data storage, I learned Android Data Persistence technology, including file storage, shared preferences storage and database storage. The data saved by these persistence technologies can only be accessed in the current application. However, in Android development, sometimes you will access the data of other applications. In order to realize the function of sharing data across programs, Android system provides a component ContentProvider (content provider). This chapter will explain the content providers in detail.
1, Content provider overview
target
- Be familiar with content providers and be able to summarize the working principle of content providers
Content provider is one of the four components of Android system. It is a standard API for data sharing between different applications. The shared data in content provider can be accessed through ContentResolver class. The working principle of ContentProvider is as follows:
data model
The ContentProvider uses a simple table based on the database model to provide data to be shared. In this table, each row represents a record, and each column represents data of a specific type and meaning, and each data record contains a field class named "_ID" to identify each data.
Uri
ContentResolver provides a series of methods for adding, deleting, modifying and querying data, and these methods provide data externally in the form of URI. Uri establishes a unique identifier for the data in the content provider. It is mainly composed of three parts: scheme, authorities and path.
2, Create content provider
target
- Master the creation method of content providers and be able to create content providers independently
To create a content provider
(1) Select the package name and right-click to select [New] - [Other] - [Content Provider]
(2) Enter the Class Name and URI Authorities of the content provider
(3) Click "Finish" to Finish the creation
After the content provider is created, Android Studio will automatically create a content provider in Android manifest Register the content provider in XML.
<application ......> ...... <provider android:name=".MyContentProvider" android:authorities="cn.itcast.mycontentprovider" android:enabled="true" android:exported="true" > </provider> </application>
3, Access other applications
target
- Master the steps of using content providers to access other applications, and be able to read the mobile phone address book
3.1 query other program data
The specific steps of querying other program data through ContentProvider are as follows:
- Parse Uri through parse() method
Uri uri = Uri.parse("content://cn.itcast.mycontentprovider/person");
- Query data through the query() method
//Get ContentResolver object ContentResolver resolver = context.getContentResolver(); Cursor cursor = resolver.query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);
- Traverse the queried data through the while() loop statement
while (cursor.moveToNext()) { String address = cursor.getString(0); long date = cursor.getLong(1); int type = cursor.getInt(2); } cursor.close(); //Close cursor
3.2 UriMatcher class
If a ContentProvider contains multiple data sources (such as multiple tables), different URIs need to be distinguished. At this time, the UriMatcher class can be used to match the URIs. The matching steps are as follows:
1. Initialize UriMatcher class
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
2. Uri required for registration
//The first parameter: the authority part of Uri //The second parameter: the path part of Uri //The third parameter: the matching code returned after Uri matching is successful matcher.addURI("cn.itcast.contentprovider", "people", PEOPLE); matcher.addURI("cn.itcast.contentprovider", "person/#", PEOPLE_ID);
3. Match with the registered Uri
Uri uri = Uri.parse("content://" + "cn.itcast.contentprovider" + "/people"); int match = matcher.match(uri); switch (match){ case PEOPLE: //Related operations after successful matching case PEOPLE_ID: //Related operations after successful matching default: return null; }
3.3 actual combat drill - reading mobile phone address book
In this section, we will use a case of reading mobile phone address book to demonstrate how to use ContentResolver to operate the data exposed in the address book of Android device. The interface effect of this case is shown in the figure below.
Place interface control res\layout\activity_contact.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#eaeaea" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="50dp" android:background="#4889f4" android:gravity="center" android:text="mail list" android:textColor="@android:color/white" android:textSize="20sp"/> <android.support.v7.widget.RecyclerView android:id="@+id/rv_contact" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="5dp" /> </LinearLayout>
Build list entry res\layout\contact_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="@drawable/item_bg" android:orientation="horizontal" android:padding="8dp"> <ImageView android:id="@+id/iv_photo" android:layout_width="60dp" android:layout_height="60dp" android:src="@drawable/contact_photo" /> <LinearLayout android:layout_width="match_parent" android:layout_height="60dp" android:layout_marginLeft="8dp" android:gravity="center_vertical" android:orientation="vertical"> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@android:color/black" android:textSize="16sp" /> <TextView android:id="@+id/tv_phone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="6dp" android:textColor="@android:color/darker_gray" android:textSize="14sp" /> </LinearLayout> </LinearLayout>
Encapsulates the entity class contacts \ contactinfo java
package cn.itcast.contacts; public class ContactInfo { private String contactName; //Contact Name private String phoneNumber; //Telephone number public String getContactName() { return contactName; } public void setContactName(String contactName) { this.contactName = contactName; } public String getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; } }
Write list adapter contacts \ contactadapter java
package cn.itcast.contacts; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import java.util.List; public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter .MyViewHolder> { private Context mContext; private List<ContactInfo> contactInfoList; public ContactAdapter(Context context, List<ContactInfo> contactInfoList) { this.mContext = context; this.contactInfoList = contactInfoList; } // inflate() loads the layout file contact_item.xml @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { MyViewHolder holder = new MyViewHolder( LayoutInflater.from(mContext).inflate( R.layout.contact_item, parent, false)); return holder; } //setText() binds the passed data to the interface control @Override public void onBindViewHolder(MyViewHolder holder, int position) { holder.tv_name.setText(contactInfoList.get(position).getContactName()); holder.tv_phone.setText(contactInfoList.get(position).getPhoneNumber()); } // Get the total number of data in contactInfoList @Override public int getItemCount() { return contactInfoList.size(); } class MyViewHolder extends RecyclerView.ViewHolder { TextView tv_name, tv_phone; ImageView iv_photo; // findViewById() to get the control on the interface public MyViewHolder(View view) { super(view); tv_name = view.findViewById(R.id.tv_name); tv_phone = view.findViewById(R.id.tv_phone); iv_photo = view.findViewById(R.id.iv_photo); } } }
Display interface data contacts \ contactactivity java
package cn.itcast.contacts; import android.content.pm.PackageManager; import android.database.Cursor; import android.os.Build; import android.provider.ContactsContract; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class ContactActivity extends AppCompatActivity { private ContactAdapter adapter; private RecyclerView rv_contact; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_contact); init(); } // 5. Display the acquired data on the address book interface private void setData() { // getContacts() is used to get the data in the phone address book List<ContactInfo> contactInfos = getContacts(); // Create data adapter adapter = new ContactAdapter(ContactActivity.this, contactInfos); // Set the adapter object to the list control RV_ On contact rv_contact.setAdapter(adapter); } // 4. Get the data of mobile phone address book public List<ContactInfo> getContacts() { List<ContactInfo> contactInfos = new ArrayList<>(); // Get the address book data and store it in the cursor object Cursor cursor = getContentResolver().query(ContactsContract. Contacts.CONTENT_URI, null, null, null, null); if (contactInfos != null) contactInfos.clear(); //Clear data from collection // Get the contact name and phone number and set them in the object of the contactInfo class while (cursor.moveToNext()) { String id = cursor.getString( cursor.getColumnIndex(ContactsContract.Contacts._ID)); String name = cursor.getString(cursor.getColumnIndex(ContactsContract. Contacts.DISPLAY_NAME)); int isHas = Integer.parseInt(cursor.getString(cursor.getColumnIndex( ContactsContract.Contacts.HAS_PHONE_NUMBER))); if (isHas > 0) { Cursor c = getContentResolver().query(ContactsContract. CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id, null, null); // Add the object of contactInfo class to the collection contactInfo while (c.moveToNext()) { ContactInfo info = new ContactInfo(); info.setContactName(name); String number = c.getString(c.getColumnIndex(ContactsContract. CommonDataKinds.Phone.NUMBER)).trim(); number = number.replace(" ", ""); number = number.replace("-", ""); info.setPhoneNumber(number); contactInfos.add(info); } c.close(); } } cursor.close(); return contactInfos; } // 1. Initialize interface controls private void init() { // Get list control rv_contact rv_contact = findViewById(R.id.rv_contact); // Set the direction of the list to vertical rv_contact.setLayoutManager(new LinearLayoutManager(this)); // Apply for permission to read mobile phone address book getPermissions(); } String[] permissionList; // 2. Apply for permission to read mobile phone address book public void getPermissions() { if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { permissionList = new String[]{"android.permission.READ_CONTACTS"}; ArrayList<String> list = new ArrayList<String>(); // Loop to determine which of the permissions required by the permissionList has not been authorized, and add it to the list for (int i = 0; i < permissionList.length; i++) { if (ActivityCompat.checkSelfPermission(this, permissionList[i]) != PackageManager.PERMISSION_GRANTED) list.add(permissionList[i]); } // There are unauthorized permissions, so the requestPermissions() method is called to request these permissions if (list.size() > 0) { ActivityCompat.requestPermissions(this, list.toArray(new String[list.size()]), 1); } else { setData();//Create the method later } } else { setData(); //Create the method later } } // 3. Get the return information of whether the application for address book permission information is successful // requestCode // Permission array of permissions system // grantResults status of the request permission @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == 1) { for (int i = 0; i < permissions.length; i++) { // Judge whether the returned permission array permissions contains the permission to read the address book: "android.permission.READ_CONTACTS" // And whether the status value grantResults of this permission is allowed to read the address book of Android device: packagemanager PERMISSION_ GRANTED if (permissions[i].equals("android.permission.READ_CONTACTS") && grantResults[i] == PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "Successfully applied for permission to read address book", Toast.LENGTH_SHORT).show(); setData();//Create the method later } else { Toast.makeText(this, "Application for reading address book permission failed", Toast.LENGTH_SHORT).show(); } } } } }
4, Content observer
target
- Master the use of content observers, and be able to use content observers to observe the data changes of other programs
4.1 what is a content observer
The content observer is used to observe the change of the data represented by the specified Uri. When the content observer observes the change of the data represented by the specified Uri, it will trigger the onChange() method. At this time, the changed data can be queried by using the contentresolver in the onChange() method.
To observe changes in data with ContentObserver, you must invoke the notifyChange() method of ContentResolver in ContentProvider.
The specific steps of observing the data represented by a specific Uri through the onChange() method in ContentObserver are as follows:
1. Create a content observer
private class MyObserver extends ContentObserver{ //Create content observer public MyObserver(Handler handler) { super(handler); } // This method is called when the data represented by Uri is observed to change, and the relevant logic is processed in this method public void onChange(boolean selfChange) { super.onChange(selfChange); } }
2. Registered content observer
ContentResolver resolver = getContentResolver(); Uri uri = Uri.parse("content://aaa.bbb.ccc"); //Registered content observer //First parameter URI URI of content provider //The second parameter is true Indicates that other URIs derived from Uri can be matched. If false, only the currently provided Uri will be matched //The third parameter is new MyObserver(new Handler()) Represents the created content observer resolver.registerContentObserver(uri, true, new MyObserver(new Handler()));
The prototype method of registering content observers is:
public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)
Function: register a ContentObserver derived class instance for the specified Uri. When the specified Uri changes, call back the instance object for processing.
Parameter 1: Uri the Uri to be observed
Parameter 2: notifyfordescendants false means that only the Uri can be matched. True means that the derived Uri can be matched at the same time
Parameter 3: content observer object created by observer
3. Cancel content observer
@Override protected void onDestroy() { super.onDestroy(); // Unregistered content watcher getContentResolver().unregisterContentObserver(new MyObserver(new Handler())); }
be careful:
In the ContentProvider monitored by the content observer, the overridden insert() method, delete() method and update() method will call the notifyChange() method of ContentResolver.
notifyChange(uri, null): used to notify all listeners registered on the Uri that the data shared by the ContentProvider has changed
- The first parameter: indicates Uri
- The second parameter: indicates the content observer. null indicates that the data shared by the ContentProvider has changed
4.2 actual combat drill - monitoring data changes
This section explains how to use content observers by detecting data changes. The interface effect of this case is shown in the figure below.
Place interface control res\layout\activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg" android:orientation="vertical"> <Button android:id="@+id/btn_insert" android:layout_width="120dp" android:layout_height="40dp" android:layout_marginLeft="40dp" android:layout_marginTop="30dp" android:background="@drawable/btn_bg" android:text="add to" android:textColor="#006000" android:textSize="20dp" /> <Button android:id="@+id/btn_update" android:layout_width="120dp" android:layout_height="40dp" android:layout_marginLeft="80dp" android:layout_marginTop="30dp" android:background="@drawable/btn_bg" android:text="to update" android:textColor="#006000" android:textSize="20dp" /> <Button android:id="@+id/btn_delete" android:layout_width="120dp" android:layout_height="40dp" android:layout_marginLeft="120dp" android:layout_marginTop="30dp" android:background="@drawable/btn_bg" android:text="delete" android:textColor="#006000" android:textSize="20dp" /> <Button android:id="@+id/btn_select" android:layout_width="120dp" android:layout_height="40dp" android:layout_marginLeft="160dp" android:layout_marginTop="30dp" android:background="@drawable/btn_bg" android:text="query" android:textColor="#006000" android:textSize="20dp" /> </LinearLayout>
Create database contentoberverdb \ persondbopenhelper java
package cn.itcast.contentobserverdb; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class PersonDBOpenHelper extends SQLiteOpenHelper { //Construct a method and call this method to create a person DB database public PersonDBOpenHelper(Context context) { // Context context // The name of the 'person.db' database // Query result set for null database // 1 version number of the database // When the super() method is called, the program creates a database named person super(context, "person.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { //While creating the database, create an info table with_ ID and name fields db.execSQL("create table info (_id integer primary key autoincrement, name varchar(20))"); } // This method will be called back when the database version is upgraded, and the database will be upgraded in this method @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
Create content provider
package cn.itcast.contentobserverdb; 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; //Realize the function of operating the data in the database public class PersonProvider extends ContentProvider { //Define a matcher of uri path. If the path matching is unsuccessful, return - 1 private static UriMatcher mUriMatcher = new UriMatcher(-1); private static final int SUCCESS = 1; //Return code when the matching path is successful private PersonDBOpenHelper helper; //Object of database operation class //Add the rule of path matcher. The static code block is executed at program startup and only once. static { mUriMatcher.addURI("cn.itcast.contentobserverdb", "info", SUCCESS); } @Override public boolean onCreate() { //Called when the content provider is created helper = new PersonDBOpenHelper(getContext()); return false; } /** * Query data operation */ @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { //Matches the Uri path of the query. If it succeeds, it returns SUCCESS. If it fails, it throws an illegal parameter exception: IllegalArgumentException int code = mUriMatcher.match(uri); if (code == SUCCESS) { SQLiteDatabase db = helper.getReadableDatabase(); // Query the information of info table and return return db.query("info", projection, selection, selectionArgs, null, null, sortOrder); } else { throw new IllegalArgumentException("Incorrect path, unable to query data!"); } } /** * Add data operation */ @Override public Uri insert(Uri uri, ContentValues values) { int code = mUriMatcher.match(uri); if (code == SUCCESS) { SQLiteDatabase db = helper.getReadableDatabase(); long rowId = db.insert("info", null, values); if (rowId > 0) { // ROWID > 0 indicates that the data is added successfully. Rebuild a Uri through the withappendedd() method // Uri URI of the content provider PersonProvider // rowId the row id of the added data in the database table Uri insertedUri = ContentUris.withAppendedId(uri, rowId); //The notifyChange() method notifies the content observer registered on the program Uri that data has changed getContext().getContentResolver().notifyChange(insertedUri, null); return insertedUri; } db.close(); return uri; } else { throw new IllegalArgumentException("Incorrect path, unable to insert data!"); } } /** * Delete data operation */ @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int code = mUriMatcher.match(uri); if (code == SUCCESS) { SQLiteDatabase db = helper.getWritableDatabase(); int count = db.delete("info", selection, selectionArgs); //Prompt that the content of the database has changed if (count > 0) { getContext().getContentResolver().notifyChange(uri, null); } db.close(); return count; } else { throw new IllegalArgumentException("The path is incorrect. You can't delete data casually!"); } } /** * Update data operation */ @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int code = mUriMatcher.match(uri); if (code == SUCCESS) { SQLiteDatabase db = helper.getWritableDatabase(); int count = db.update("info", values, selection, selectionArgs); //Prompt that the content of the database has changed if (count > 0) { getContext().getContentResolver().notifyChange(uri, null); } db.close(); return count; } else { throw new IllegalArgumentException("Incorrect path, unable to update data!"); } } @Override public String getType(Uri uri) { return null; } }
Write interface interaction code
package cn.itcast.contentobserverdb; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private ContentResolver resolver; private Uri uri; private ContentValues values; private Button btnInsert; private Button btnUpdate; private Button btnDelete; private Button btnSelect; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //Initialization interface createDB(); //Create database } // Initialize the interface control and set the click listening event of the control private void initView() { btnInsert = findViewById(R.id.btn_insert); btnUpdate = findViewById(R.id.btn_update); btnDelete = findViewById(R.id.btn_delete); btnSelect = findViewById(R.id.btn_select); btnInsert.setOnClickListener(this); btnUpdate.setOnClickListener(this); btnDelete.setOnClickListener(this); btnSelect.setOnClickListener(this); } private void createDB() { //When you create the helper object, you also create person DB database PersonDBOpenHelper helper = new PersonDBOpenHelper(this); // Gets the object db of the database class SQLiteDatabase SQLiteDatabase db = helper.getWritableDatabase(); // Insert three pieces of data into the database info table for (int i = 0; i < 3; i++) { ContentValues values = new ContentValues(); values.put("name", "itcast" + i); db.insert("info", null, values); } db.close(); } @Override public void onClick(View v) { //Get a parsing object of the content provider resolver = getContentResolver(); //Get a Uri path uri = Uri.parse("content://cn.itcast.contentobserverdb/info"); //Create a new ContentValues object, which adds data to the database table in the form of key values values = new ContentValues(); switch (v.getId()) { case R.id.btn_insert: Random random = new Random(); // Add the data to be added to the values object values.put("name", "add_itcast" + random.nextInt(10)); // Add the data in the values object to the database // Uri URI of the content provider PersonProvider // values data to add Uri newuri = resolver.insert(uri, values); // Toast and Log are used to prompt for successful addition Toast.makeText(this, "Added successfully", Toast.LENGTH_SHORT).show(); Log.i("Database application", "add to"); break; case R.id.btn_delete: //Returns the number of entries for deleted data int deleteCount = resolver.delete(uri, "name=?", new String[]{"itcast0"}); Toast.makeText(this, "Successfully deleted" + deleteCount + "that 's ok", Toast.LENGTH_SHORT).show(); Log.i("Database application", "delete"); break; case R.id.btn_select: List<Map<String, String>> data = new ArrayList<Map<String, String>>(); //Returns the query result, which is a cursor pointing to the result set Cursor cursor = resolver.query(uri, new String[]{"_id", "name"}, null, null, null); //Traverse the data in the result set, and store each traversal result in a List collection while (cursor.moveToNext()) { Map<String, String> map = new HashMap<String, String>(); map.put("_id", cursor.getString(0)); map.put("name", cursor.getString(1)); data.add(map); } //Close the cursor to release resources cursor.close(); Log.i("Database application", "Query results:" + data.toString()); break; case R.id.btn_update: //Change the record whose name is itcast1 in the database info table to name is update_itcast values.put("name", "update_itcast"); int updateCount = resolver.update(uri, values, "name=?", new String[]{"itcast1"}); Toast.makeText(this, "Successfully updated" + updateCount + "that 's ok", Toast.LENGTH_SHORT).show(); Log.i("Database application", "to update"); break; } } }
So far, the program for operating the database has been created. Next, the program for monitoring the change of the database is created. The specific steps are as follows:
monitordata\MainActivity.java
package cn.itcast.monitordata; import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.v7.app.AppCompatActivity; import android.util.Log; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // The uri path points to the database info table in the database application Uri uri = Uri.parse("content://cn.itcast.contentobserverdb/info"); //Registered content observer, // The parameter uri points to the database info table to be monitored, //The parameter true defines the monitoring range, // The last parameter is a content observer object getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler())); } private class MyObserver extends ContentObserver { public MyObserver(Handler handler) {//handler is a message processor. super(handler); } @Override //This method is executed when the data in the info table changes public void onChange(boolean selfChange) { Log.i("Monitoring data changes", "Someone moved your database!"); super.onChange(selfChange); } } @Override protected void onDestroy() { super.onDestroy(); //Unregister content watcher getContentResolver().unregisterContentObserver(new MyObserver( new Handler())); } }
be careful:
The purpose of the content observer is to observe the changes of the database caused by a specific Uri, and then do some corresponding processing. This method has high efficiency and low memory consumption, which needs to be mastered by beginners.
ntentobserverdb/info");
//Registered content observer,
//The parameter uri points to the database info table to be monitored,
//The parameter true defines the monitoring range,
//The last parameter is a content observer object
getContentResolver().registerContentObserver(uri, true,
new MyObserver(new Handler()));
}
private class MyObserver extends ContentObserver { public MyObserver(Handler handler) {//handler is a message processor. super(handler); } @Override //This method is executed when the data in the info table changes public void onChange(boolean selfChange) { Log.i("Monitoring data changes", "Someone moved your database!"); super.onChange(selfChange); } } @Override protected void onDestroy() { super.onDestroy(); //Unregister content watcher getContentResolver().unregisterContentObserver(new MyObserver( new Handler())); }
}
be careful: <font color='red'>The purpose of the content observer is to observe a specific content Uri Caused by the changes in the database, and then do some corresponding processing. This method has high efficiency and less memory consumption, which needs to be mastered by beginners.</font>