brief introduction
ContentProvider Android Its function is to share data with the outside world, that is to say, you can share the data in the application to other applications through ContentProvider, and other applications can access it through ContentProvider.
Add, delete, and check the data in your application. As for data sharing, we have learned the file operation mode before, and we know that data can also be shared outside by specifying the file operation mode as Context.MODE_WORLD_READABLE or Context.MODE_WORLD_WRITEABLE. So why use ContentProvider to share data? In this way, if we use file operation mode to share data, the way of accessing data will be different because of the way of data storage, which leads to the inconsistency of the way of accessing data. For example, using xml file to share data, we need xml parsing to read data; using sharedpreferences to share data, we need to use sharedpreferences to share data.
API reads data.
The advantage of using ContentProvider to share data with the outside world is to unify the way of accessing data.
The principle of ContentProvider is to expose its own interface to other applications according to certain rules to access the data of its own application (in fact, it is to customize the add, delete, modify and check interface and expose it so that other applications can access their own data).
ContentResolver is to access the content provider's data according to certain rules (in fact, calling the content provider's custom interface to manipulate its data).
ContentProvider Shares Data Outside:
step
1. Define a class to inherit ContentProvider
2. Define matching rules to specify host name + path code urimatcher content:.//
3. Adding matching rules through static code blocks
4. Be sure to configure the content provider in the manifest file and don't forget to add authorities.
Explain:
The first step to inherit ContentProvider requires rewriting the following methods:
public class PersonContentProvider extends ContentProvider{
public boolean onCreate()
public Uri insert(Uri uri, ContentValues values)
public int delete(Uri uri, String selection, String[] selectionArgs)
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String
sortOrder)
public String getType(Uri uri)}
The fourth step is to configure the ContentProvider in Android Manifest. XML using <provider> so that other applications can find the ContentProvider, ContentProvider
Using authorities (host name/domain name) to uniquely identify it, you can think of ContentProvider as a website (think, the website is also a data provider), and authorities is his domain name:
<manifest .... >
<application android:icon="@drawable/icon" android:label="@string/app_name">
<provider android:name=".PersonContentProvider" android:authorities="cn.itcast.providers.personprovider"/>
</application>
</manifest>
The role of the main methods of the ContentProvider class:
public boolean onCreate()
This method is called when the ContentProvider is created, and when Android is turned on, the ContentProvider is created when other applications first visit it.
public Uri insert(Uri uri, ContentValues values)
This method is used for external applications to add data to ContentProvider.
public int delete(Uri uri, String selection, String[] selectionArgs)
This method is used for external applications to delete data from ContentProvider.
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
This method is used to update data in ContentProvider for external applications.
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
This method is used for external applications to obtain data from ContentProvider.
public String getType(Uri uri)
This method is used to return the MIME type of the data represented by the current Url. If the operation data belongs to the set type, the MIME type string should begin with vnd.android.cursor.dir/.
For example, to get the Uri of all person records as content://cn.itcast.provider.person provider/person, the MIME type string returned should be: "vnd.android.cursor.dir/person". If the data to be operated on belongs to non-set type data, the MIME type string should begin with vnd.android.cursor.item/e.g. get a person record with id 10 and Uri as content://cn.itcast.provider.person provider/person/10, then the returned MIME type string should be: "vnd.android.cursor.item/person".
Uri introduction
Uri represents the data to be operated on. Uri mainly contains two parts of information: 1) ContentProvider to be operated on, 2) What data to be operated on in ContentProvider. A Uri consists of the following parts:
ContentProvider's scheme has been defined by Android, which is: content:://
The host name (or Authority) is used to uniquely identify the ContentProvider, which can be found by external callers.
path can be used to represent the data we want to operate on. path construction should be based on business, as follows:
To manipulate the record with id 10 in the person table, you can construct such a path: / person/10
To manipulate the name field of the record with id 10 in the person table, person/10/name
To manipulate all records in the person table, you can construct a path: / person
To manipulate records in XXX tables, you can construct a path: / xxx
Of course, the data to be operated on does not necessarily come from the database, but can also be stored in other ways such as files, xml or networks, as follows:
To manipulate the name node under the person node in the xml file, you can construct the path: / person/name
If you want to convert a string to Uri, you can use the parse() method in the Uri class, as follows:
Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person")
Introduction to the Use of UriMatcher Class
Because Uri represents the data to be manipulated, we often need to parse Uri and retrieve data from Uri. The Android system provides two tool classes for manipulating Uri, UriMatcher and ContentUris.
Mastering their use will facilitate our development work.
The UriMatcher class is used to match Uri, and its usage is as follows:
The first step is to register all the Uri paths you need to match, as follows:
// Constant UriMatcher.NO_MATCH denotes a return code that does not match any path
UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// If the match() method matches the content://cn.itcast.provider.person provider/person path, the return matching code is 1.
sMatcher.addURI("cn.itcast.provider.personprovider", "person", 1); // Add a matching uri, if matched, the matching code will be returned.
// If the match() method matches the content://cn.itcast.provider.person provider/person/230 path, the return matching code is 2.
sMatcher.addURI("cn.itcast.provider.personprovider", "person/ 2);// is a wildcard character
switch (sMatcher.match(Uri.parse("content://cn.itcast.provider.personprovider/person/10"))) {
case 1
break;
case 2
break;
default://mismatch
break;
}
After registering the Uri that needs to be matched, the input Uri can be matched using the sMatcher.match(uri) method. If matched, the matching code is returned. The matching code is the third parameter passed in by calling the addURI() method.
Assuming that the matching content://cn.itcast.provider.person provider/person path is matched, the matching code returned is 1
Code example
-
package com.itheima.transaction;
-
-
import android.content.ContentProvider;
-
import android.content.ContentValues;
-
import android.content.UriMatcher;
-
import android.database.Cursor;
-
import android.database.sqlite.SQLiteDatabase;
-
import android.net.Uri;
-
-
public class AccountProvider extends ContentProvider {
-
-
private static final int QUEYSUCESS = 0;
-
private static final int INSERTSUCESS = 1;
-
-
private static final int UPDATESUCESS = 2;
-
-
private static final int DELSUCESS = 3;
-
-
-
static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
-
-
private MyOpenHelper helper;
-
-
-
-
static{
-
-
-
-
-
-
-
matcher.addURI("com.itheima.contentprovider", "query", QUEYSUCESS);
-
-
matcher.addURI("com.itheima.contentprovider", "insert", INSERTSUCESS);
-
-
matcher.addURI("com.itheima.contentprovider", "update", UPDATESUCESS);
-
-
matcher.addURI("com.itheima.contentprovider", "delete", DELSUCESS);
-
-
-
}
-
-
-
@Override
-
public boolean onCreate() {
-
helper = new MyOpenHelper(getContext());
-
-
-
-
return false;
-
}
-
-
-
@Override
-
public Cursor query(Uri uri, String[] projection, String selection,
-
String[] selectionArgs, String sortOrder) {
-
-
int match = matcher.match(uri);
-
if (match == QUEYSUCESS ) {
-
-
SQLiteDatabase db = helper.getReadableDatabase();
-
Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder);
-
-
-
-
-
getContext().getContentResolver().notifyChange(uri, null);
-
-
return cursor;
-
-
}else{
-
-
throw new IllegalArgumentException("Path Matching Failure");
-
-
}
-
-
-
}
-
-
@Override
-
public String getType(Uri uri) {
-
return null;
-
}
-
-
@Override
-
public Uri insert(Uri uri, ContentValues values) {
-
-
int match = matcher.match(uri);
-
if (match == INSERTSUCESS) {
-
-
SQLiteDatabase db = helper.getReadableDatabase();
-
long insert = db.insert("info", null, values);
-
-
-
-
if (insert>0) {
-
-
-
getContext().getContentResolver().notifyChange(uri, null);
-
}
-
-
-
-
-
Uri uri2 = Uri.parse("com.itheima.contentprovider/"+insert);
-
return uri2;
-
}else{
-
-
throw new IllegalArgumentException("Path Matching Failure");
-
-
}
-
-
}
-
-
@Override
-
public int delete(Uri uri, String selection, String[] selectionArgs) {
-
int match = matcher.match(uri);
-
if (match == DELSUCESS) {
-
-
SQLiteDatabase db = helper.getReadableDatabase();
-
int delete = db.delete("info", selection, selectionArgs);
-
-
if (delete>0) {
-
-
getContext().getContentResolver().notifyChange(uri, null);
-
-
}
-
-
-
return delete;
-
-
}else {
-
-
-
throw new IllegalArgumentException("Path Matching Failure");
-
-
}
-
-
}
-
-
@Override
-
public int update(Uri uri, ContentValues values, String selection,
-
String[] selectionArgs) {
-
-
int match = matcher.match(uri);
-
if (match == UPDATESUCESS) {
-
-
SQLiteDatabase db = helper.getReadableDatabase();
-
int update = db.update("info", values, selection, selectionArgs);
-
-
if (update>0) {
-
-
getContext().getContentResolver().notifyChange(uri, null);
-
}
-
-
return update;
-
}else {
-
-
throw new IllegalArgumentException("Path Matching Failure");
-
}
-
-
}
-
-
}
ContentResolver
Use ContentResolver to call the interface provided by ContentProvider to manipulate data
When external applications need to add, delete, modify and query the data in ContentResolver, they can use the ContentResolver class to complete the task. They want to get the ContentResolver object.
You can use the getContentResolver() method provided by Activity. The ContentResolver class provides four methods for signing the same signature as the ContentProvider class:
public Uri insert(Uri uri, ContentValues values)
This method is used to add data to ContentProvider.
public int delete(Uri uri, String selection, String[] selectionArgs)
This method is used to delete data from ContentProvider.
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
This method is used to update data in ContentProvider.
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
This method is used to obtain data from ContentProvider.
The first parameter of these methods is Uri, which represents the Content Provider to be operated on and what data to operate on. Assuming that given Uri.parse("content://cn.itcast.providers.personprovider/person/10"), the Content Provider named cn.itcast.providers.personprovider will be operated on. The data to be operated on is a record of id 10 in the person table. Record.
-
Use ContentResolver Yes ContentProvider Add, delete, modify and query the data in:
-
ContentResolver resolver = getContentResolver();
-
Uri uri = Uri.parse("content://cn.itcast.provider.personprovider/person");
-
-
ContentValues values = new ContentValues();
-
values.put("name", "itcast");
-
values.put("age", 25);
-
resolver.insert(uri, values);
-
-
Cursor cursor = resolver.query(uri, null, null, null, "personid desc");
-
while(cursor.moveToNext()){
-
Log.i("ContentTest", "personid="+ cursor.getInt(0)+ ",name="+ cursor.getString(1));
-
}
-
-
ContentValues updateValues = new ContentValues();
-
updateValues.put("name", "liming");
-
resolver.update(updateIdUri, updateValues, null, null);
Monitor data changes in ContentProvider
If visitors to ContentProvider need to know that the data in ContentProvider has changed, they can call when the data changes in ContentProvider.
getContentResolver().notifyChange(uri, null) notifies visitors registered on this URI, as follows:
-
public class PersonContentProvider extends ContentProvider {
-
public Uri insert(Uri uri, ContentValues values) {
-
db.insert("person", "personid", values);
-
getContext().getContentResolver().notifyChange(uri, null);
-
}
-
}
If visitors to ContentProvider need to be notified of data changes, they must use ContentObserver to listen for data (data is described by uri). When they listen for data change notifications,
The system calls the onChange() method of ContentObserver:
-
getContentResolver().registerContentObserver(Uri.parse("content://cn.itcast.providers.personprovider/person"),
-
true,
-
new PersonObserver(new Handler()));
-
public class PersonObserver extends ContentObserver{
-
public PersonObserver(Handler handler) {
-
super(handler);
-
}
-
public void onChange(boolean selfChange) {
-
-
}
-
}
Example code
Backup SMS with Content Analyser
-
package com.itheima.backupsms;
-
-
import java.io.File;
-
import java.io.FileNotFoundException;
-
import java.io.FileOutputStream;
-
import java.io.IOException;
-
-
import org.xmlpull.v1.XmlSerializer;
-
-
import android.net.Uri;
-
import android.os.Bundle;
-
import android.os.Environment;
-
import android.os.FileObserver;
-
import android.app.Activity;
-
import android.database.Cursor;
-
import android.util.Xml;
-
import android.view.Menu;
-
import android.view.View;
-
-
public class MainActivity extends Activity {
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
}
-
-
-
-
-
-
-
public void backup(View v) {
-
-
try {
-
-
XmlSerializer serializer = Xml.newSerializer();
-
-
File file = new File(Environment.getExternalStorageDirectory()
-
.getPath(), "smsbackup.xml");
-
FileOutputStream fos = new FileOutputStream(file);
-
serializer.setOutput(fos, "utf-8");
-
-
-
serializer.startDocument("utf-8", true);
-
-
-
serializer.startTag(null, "smss");
-
-
Uri uri = Uri.parse("content://sms");
-
-
Cursor cursor = getContentResolver().query(uri,
-
new String[] { "address", "date", "body" }, null, null,
-
null);
-
while (cursor.moveToNext()) {
-
-
serializer.startTag(null, "sms");
-
String address = cursor.getString(0);
-
String date = cursor.getString(1);
-
String body = cursor.getString(2);
-
-
-
serializer.startTag(null, "address");
-
serializer.text(address);
-
serializer.endTag(null, "address");
-
-
-
serializer.startTag(null, "date");
-
serializer.text(date);
-
serializer.endTag(null, "date");
-
-
-
-
serializer.startTag(null, "body");
-
serializer.text(body);
-
serializer.endTag(null, "body");
-
-
serializer.endTag(null, "sms");
-
}
-
-
-
-
serializer.endTag(null, "smss");
-
-
-
serializer.endDocument();
-
-
} catch (Exception e) {
-
e.printStackTrace();
-
}
-
-
}
-
-
}
Inserting SMS with Content Parser
-
-
Uri uri = Uri.parse("content://sms");
-
ContentValues values = new ContentValues();
-
values.put("address", "110");
-
values.put("date", System.currentTimeMillis());
-
values.put("body", "You've done something wrong. Please come at once.");
-
getContentResolver().insert(uri, values);
Using Content Analyser to Get Contact Data
1. First, I need to query the raw_contacts table to get contact_id.
2. Get the data of mimetype data1 from the data table according to contact_id
3. Then differentiate the data types according to mimetype_id.
-
package com.itheima.getcontactinfo.utils;
-
-
import java.util.ArrayList;
-
import java.util.List;
-
-
import android.content.ContentResolver;
-
import android.content.Context;
-
import android.database.Cursor;
-
import android.net.Uri;
-
-
import com.itheima.getcontactinfo.domain.ContactInfo;
-
-
public class ContactUtils {
-
-
public static List<ContactInfo> getContactInfos(Context context) {
-
-
List<ContactInfo> contactLists = new ArrayList<ContactInfo>();
-
-
-
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
-
Uri datauri = Uri.parse("content://com.android.contacts/data");
-
-
ContentResolver resolver = context.getContentResolver();
-
Cursor cursor = resolver.query(uri, new String[] { "contact_id" },
-
null, null, null);
-
while (cursor.moveToNext()) {
-
-
String contact_id = cursor.getString(0);
-
System.out.println("contact_id--" + contact_id);
-
-
-
if (contact_id != null) {
-
-
ContactInfo info = new ContactInfo();
-
info.setId(contact_id);
-
-
-
-
Cursor dataCursor = resolver.query(datauri, new String[] {
-
"mimetype", "data1" }, "raw_contact_id=?",
-
new String[] { contact_id }, null);
-
while (dataCursor.moveToNext()) {
-
String mimetype = dataCursor.getString(0);
-
String data1 = dataCursor.getString(1);
-
-
-
if ("vnd.android.cursor.item/email_v2".equals(mimetype)) {
-
info.setEmail(data1);
-
-
} else if ("vnd.android.cursor.item/name".equals(mimetype)) {
-
-
info.setName(data1);
-
-
} else if ("vnd.android.cursor.item/phone_v2"
-
.equals(mimetype)) {
-
System.out.println("data---Telephone number?-" + data1);
-
info.setPhone(data1);
-
}
-
-
}
-
dataCursor.close();
-
contactLists.add(info);
-
-
}
-
-
}
-
cursor.close();
-
-
return contactLists;
-
-
}
-
-
}
-
package com.itheima.getcontactinfo.domain;
-
-
public class ContactInfo {
-
-
private String id;
-
private String name;
-
private String phone;
-
private String email;
-
-
-
-
public String getId() {
-
return id;
-
}
-
public void setId(String id) {
-
this.id = id;
-
}
-
public String getName() {
-
return name;
-
}
-
public void setName(String name) {
-
this.name = name;
-
}
-
public String getPhone() {
-
return phone;
-
}
-
public void setPhone(String phone) {
-
this.phone = phone;
-
}
-
public String getEmail() {
-
return email;
-
}
-
public void setEmail(String email) {
-
this.email = email;
-
}
-
@Override
-
public String toString() {
-
return "ContactInfo [id=" + id + ", name=" + name + ", phone=" + phone
-
+ ", email=" + email + "]";
-
}
-
-
-
-
-
-
}
Insert contacts using content parsers
1. Insert a data into raw_contacts first
2. Insert data into the data table according to mimetype contact_id
-
package com.itheima.insert.contact;
-
-
import android.net.Uri;
-
import android.os.Bundle;
-
import android.app.Activity;
-
import android.content.ContentValues;
-
import android.database.Cursor;
-
import android.view.Menu;
-
import android.view.View;
-
import android.widget.EditText;
-
-
public class MainActivity extends Activity {
-
-
private EditText et_name;
-
private EditText et_phone;
-
private EditText et_email;
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
-
-
et_name = (EditText) findViewById(R.id.et_name);
-
et_phone = (EditText) findViewById(R.id.et_phone);
-
et_email = (EditText) findViewById(R.id.et_email);
-
-
-
-
-
}
-
-
-
-
-
-
public void click(View v){
-
-
-
String name = et_name.getText().toString().trim();
-
String phone = et_phone.getText().toString().trim();
-
String email = et_email.getText().toString().trim();
-
-
-
Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
-
Uri datauri = Uri.parse("content://com.android.contacts/data");
-
-
ContentValues values = new ContentValues();
-
-
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
-
int count = cursor.getCount();
-
int contact_id = count + 1;
-
-
values.put("contact_id", contact_id);
-
getContentResolver().insert(uri, values);
-
-
-
-
ContentValues nameValues = new ContentValues();
-
nameValues.put("data1", name);
-
nameValues.put("mimetype", "vnd.android.cursor.item/name");
-
nameValues.put("raw_contact_id", contact_id);
-
getContentResolver().insert(datauri, nameValues);
-
-
ContentValues phoneValues = new ContentValues();
-
phoneValues.put("data1", phone);
-
phoneValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
-
phoneValues.put("raw_contact_id", contact_id);
-
getContentResolver().insert(datauri, phoneValues);
-
-
ContentValues emailValues = new ContentValues();
-
emailValues.put("data1", email);
-
emailValues.put("mimetype", "vnd.android.cursor.item/email_v2");
-
emailValues.put("raw_contact_id", contact_id);
-
getContentResolver().insert(datauri, emailValues);
-
-
-
-
-
-
}
-
-
-
}
Use listeners and content parsers to listen for text messages
-
package com.itheima.smslistener;
-
-
import android.net.Uri;
-
import android.os.Bundle;
-
import android.os.Handler;
-
import android.app.Activity;
-
import android.database.ContentObserver;
-
import android.database.Cursor;
-
import android.view.Menu;
-
-
public class MainActivity extends Activity {
-
-
private Uri uri;
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
-
-
-
uri = Uri.parse("content://sms");
-
getContentResolver().registerContentObserver(uri, true, new MyObserver(new Handler()));
-
-
}
-
-
-
-
private class MyObserver extends ContentObserver{
-
-
public MyObserver(Handler handler) {
-
super(handler);
-
}
-
@Override
-
public void onChange(boolean selfChange) {
-
-
-
-
Cursor cursor = getContentResolver().query(uri, new String[]{"address","body","date"}, null, null, null);
-
while(cursor.moveToNext()){
-
-
String address = cursor.getString(0);
-
String body = cursor.getString(1);
-
String date = cursor.getString(2);
-
-
System.out.println("address---"+address+"--body:"+body);
-
-
}
-
-
super.onChange(selfChange);
-
}
-
-
-
}
-
-
}