CH6 content provider

Posted by pspeakman on Sat, 05 Mar 2022 06:06:20 +0100

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:

  1. Parse Uri through parse() method
Uri uri = Uri.parse("content://cn.itcast.mycontentprovider/person");
  1. 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);
  1. 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>

































Topics: Java Android xml