The problems to be solved are:
There are two projects A and B. Project A creates a self-produced and self-sold database through the subclass of SQLiteOpenHelper. Project B does not have a database, but Project B wants to share the same database with Project A.
To achieve the above objectives, two system classes are needed:
- One of the four components of ContentProvider content provider Andord
- ContentResolver Content Observer
The combination of the two can share data between processes (between multiple projects)
How to use it:
Engineering A (to open data to other projects):
- Prepare a subclass of SQLiteOpenHelper to manage the self-produced and self-sold database of the current project.
- In order to open up the self-produced and self-sold database, the following operations need to be done through ContentProvider:
Create a subclass of ContentProvider
b. Register a subclass of ContentProvider in the manifest file
<! - Register the ContentProvider subclass information in the application tag android:name is used to specify the specific path of the subclass android:authorities sets the name of the author corresponding to the current subclass and writes any string of attribute values. The authorities in the Uri path that are set when connecting to this class via ContentResolver in other projects later Android: export= "true" allows open data operations --> <provider android:name="com.example.day14_5_contentprovider.MyProvider" android:authorities="com.ay.sql" android:exported="true" ></provider>
c. Fill in the corresponding code in the method of adding, deleting and modifying subclasses
MyProvider subclass:
public class MyProvider ext ends ContentProvider {
//Initialize UriMatcher objects for comparing Uri path types
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final int VIP = 1;
private static final int VIP_ID = 3;
private static final int VIP_LIKE = 4;
private static final int BLACK = 2;
static {
//Adding a reference for comparison
/**
* Representatives store references to matcher objects: content://com.ay.oye/vip,
* Later, when matcher calls match method for comparison, once the same as the current reference, the return value of match method is the data 1 corresponding to VIP.
*/
matcher.addURI("com.ay.oye", "vip", VIP);
matcher.addURI("com.ay.oye", "black", BLACK);
matcher.addURI("com.ay.oye", "vip/#", VIP_ID); //# Represents any number
matcher.addURI("com.ay.oye", "vip/*", VIP_LIKE); //* Represents any character
}
private SQLiteDatabase db;
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
db = new MyHelper(getContext()).getReadableDatabase();
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
Cursor cursor = null;
switch (matcher.match(uri)) {
case VIP:
//The query is the vip table
//Encapsulate query method for query in database through db object calling system
cursor = db.query("vip", projection, selection, selectionArgs, null, null, sortOrder);
break;
case BLACK:
//The query is the black table
cursor = db.query("black", projection, selection, selectionArgs, null, null, sortOrder);
break;
case VIP_ID:
if (selection == null) {
cursor = db.query("vip", projection, "_id = "+uri.getLastPathSegment(), null, null, null, sortOrder);
} else {
cursor = db.query("vip", projection, selection+"and _id = "+uri.getLastPathSegment(), selectionArgs, null, null, sortOrder);
}
break;
case VIP_LIKE:
if (selection == null) {
cursor = db.query("vip", projection, "name like ?", new String[] {"%"+uri.getLastPathSegment()+"%"}, null, null, sortOrder);
} else {
cursor = db.query("vip", projection, selection + " and name like "+"'"+"%"+uri.getLastPathSegment()+"%"+"'", selectionArgs, null, null, sortOrder);
}
break;
}
return cursor;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return matcher.match(uri)+"";
}
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
long num = 0;
switch (matcher.match(uri)) {
case VIP:
num = db.insert("vip", "_id", values);
break;
case BLACK:
num = db.insert("black", "_id", values);
break;
}
return Uri.withAppendedPath(uri, num+"");
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
switch (matcher.match(uri)) {
case VIP:
db.delete("vip", selection, selectionArgs);
break;
case BLACK:
db.delete("black", selection, selectionArgs);
break;
case VIP_ID:
if (selection == null) {
db.delete("vip", "_id = "+uri.getLastPathSegment(), null);
} else {
db.delete("vip", selection+" and _id = "+uri.getLastPathSegment(), selectionArgs);
}
break;
case VIP_LIKE:
break;
}
return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
In Engineering B (data obtained from Engineering A):
1. Initialize the ContentResolver object
//Initialize the ContentResolver object
cr = getContentResolver();
2. Implementing database operation by calling add-delete-modify method of ContentResolver object
Such as:
public void click (View v) {
switch (v.getId()) {
case R.id.but_add:
/**
* Let's start with an example of adding
* Parameters:
* 1. Uri Used to describe paths
* Splicing features:
* scheme: // authorities / data
* scheme Theme, which represents the specific type of current path, is a file path or a phone, etc.
*
* 2.ContentValues ,Used to store data to be added
*/
ContentValues values = new ContentValues();
values.put("name", "tearful");
values.put("age", 28);
/**
* Execution process: Find out which Subclass of ContentProvider registers the same author name in all applications of the entire device based on the author name in the Uri path
* Run the insert method in this subclass after finding it
*/
Uri uri = cr.insert(Uri.parse("content://com.ay.sql/pr"), values);
//If you want to get the id value of the newly added data from the uri object returned by the insert method
String id = uri.getLastPathSegment();
Log.i("oye", "Project 6: Corresponding to the newly added data id As follows: "+id);
break;
case R.id.but_query:
/**
* Parameters:
* 1. Uri Route,
* 2. To query which columns in the table, fill in null to get all columns
* 3, Conditions for queries
* 3, For substitution conditions? Value
* 5. sort
*/
Cursor cursor = cr.query(Uri.parse("content://com.ay.sql/pr"), null, null, null, null);
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
Log.i("oye", "Data bits obtained in Engineering 6: "+name);
}
break;
case R.id.but_delete:
int num = cr.delete(Uri.parse("content://com.ay.sql/pr"), "_id=?", new String[]{"3"});
Log.i("oye", "The number of items deleted in Engineering 6 is:"+num);
break;
case R.id.but_update:
ContentValues cv = new ContentValues();
cv.put("name", "Wang Laoshi");
int num1 = cr.update(Uri.parse("content://com.ay.sql/pr"), cv, "_id = ?", new String[]{"5"});
Log.i("oye", "The number of items deleted in Engineering 6 is:"+num1);
break;
}
}
Relatively common uses such as:
The system's call record project opens the call record through ContentProvider. We want to get the information through the record, we just need to call the corresponding add-delete check method through ContentResolver.
Read common system data through ContentResolver:
1. Call Logging Information 2. Short Message Recording Information 3. Contact address book information
1. Read the call record through ContentResolver:
Prepare before reading: Make sure that the device used for testing has a call record, otherwise the content will not be read.
If it is the way the simulator processes the call record:
1. Dial-out telephone: directly use the dialing software on the simulator. 2. Answer the phone (only the native simulator can simulate the answer): Select to open the Emulator Control tag in Window-ShowVIew-Other-Android, in which the function of dialing out the phone to the simulator and sending short messages can be realized.
The storage location of the system call record table:
/* * Location of the database for call records: data/data/com.android.providers.contacts/databases/contacts 2.db * Table name: calls * Corresponding author name: call_log * Read the content through the query method */
Main columns in the call log:
number Storage Phone number Type stores the type of call, 1 for incoming calls (answered calls) and 2 for outgoing calls (dialed calls) date calls The duration of a duration call
The Uri used by the connection through the record:
Uri.parse("content://call_log/calls")
Specific reading methods:
Cursor cursor = cr.query(Uri.parse("content://call_log/calls"), null, null, null, null);
while(cursor.moveToNext()) {
//Telephone number?
String number = cursor.getString(cursor.getColumnIndex("number"));
//Is it a call or a call?
String s = cursor.getString(cursor.getColumnIndex("type"));
String type = s.equals("1") ? "Calls (answered calls)":"To call (a dialed phone)";
//time
String date = cursor.getString(cursor.getColumnIndex("date"));
//Get the length of the call
String duration = cursor.getString(cursor.getColumnIndex("duration"));
Log.i("oye", "Data bits in the voice record: "+number +" "+date+" "+type+" "+duration);
}
Permissions that need to be added:
<! - Add permission to read the call record - > <uses-permission android:name="android.permission.READ_CALL_LOG"/> <! - Add permission to modify the write-to-call record - > <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
2. Read short message records through ContentResolver:
Storage location of system short message record table:
data/data/com.android.provider.telephony/databases/mmssms.dbMedium sms surface
Uri for connection use:
content://sms
The more important columns in the table are:
address phone number date receives short messages date_sent date for sending short messages Read is used to identify whether text messages have been read, 0 for unread and 1 for read. Type is used to identify SMS received by SMS type 1, SMS sent by type 2, SMS sent by type 3, SMS sent in draft box body Short Message Content
Reading mode:
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
ContentResolver cr = getContentResolver();
Cursor cursor = cr.query(Uri.parse("content://sms"), null, null, null, null);
while (cursor.moveToNext()) {
String number = cursor.getString(cursor.getColumnIndex("address"));
String mess = cursor.getString(cursor.getColumnIndex("body"));
String read = cursor.getString(cursor.getColumnIndex("read")).equals("0") ? "Unread":"Already read";
String type = cursor.getString(cursor.getColumnIndex("type")).equals("1")?"Received SMS":"Short Messages Sended";
Log.i("oye", "The content of the short message obtained is as follows: "+number+" "+mess+" "+read+" "+type);
}
}
Required permissions:
<! - Access to SMS Records - > <uses-permission android:name="android.permission.READ_SMS"/> <! - Permission to modify SMS records - > <uses-permission android:name="android.permission.WRITE_SMS"/>
3. Reading System Address Book Contacts through ContentResolver
Storage location of contact person in system address book:
data/data/com.android.providers.contacts/databases/Contacts2.db database file
Main tables for reading contact information:
1.raw_contacts Used to store the name of a contact and the unique id value corresponding to that contact 2.data Used to store all data for all contacts, but note: (1) Not all the information of a contact is stored in one line Instead, it splits all the information of a contact into multiple rows of storage. The way to determine which rows of data belong to the same contact is: Judging by the value of raw_contact_id for each row, all data for the same contact is the same value (2) Basically, most of the data is stored in the data1 column. In order to determine the type of data (phone number or name) in the data1 column of this row, it is necessary to judge the value in the mimetype_id column. 3.Mimetypes Used to store all data class names, such as phone number, name, mailbox address, etc.
Reading mode:
Reading mode 1:
private ArrayList<MyC> queryAll() {
ArrayList<MyC> list = new ArrayList<MyC>();
// 1. Read the raw_contacts table. The purpose is to get the unique id of each person's contact. This time, all the contact id values are stored in the idCursor.
Cursor idCursor = cr.query(
Uri.parse("content://com.android.contacts/raw_contacts"), null,
"deleted = 0", null, null);
while (idCursor.moveToNext()) {
// Get the id of the contact
int id = idCursor.getInt(idCursor.getColumnIndex("_id"));
MyC myc = new MyC();
myc.setId(id);
// 2. Read the data from the data table according to the id value or obtained. The cursor object obtained this time stores a contact's multi-faceted data.
Cursor cursor = cr.query(
Uri.parse("content://com.android.contacts/data"), null,
"raw_contact_id = " + id, null, null);
// 3. Loop cursor object to read contact data
while (cursor.moveToNext()) {
// Get the value of the column data1
String data1 = cursor.getString(cursor.getColumnIndex("data1"));
Log.i("oye", "Current row data1 The data are as follows: " + data1);
String mime = cursor.getString(cursor
.getColumnIndex("mimetype"));
if (mime.equals("vnd.android.cursor.item/name")) {
// Names are stored in the data1 column representing the current row
myc.setName(data1);
} else if (mime.equals("vnd.android.cursor.item/email_v2")) {
// In data1, which represents the bank, the mailbox address is stored.
myc.setEmail(data1);
} else if (mime
.equals("vnd.android.cursor.item/postal-address_v2")) {
// Home address
myc.setAddress(data1);
} else if (mime.equals("vnd.android.cursor.item/phone_v2")) {
// Stored is the phone number.
String data2 = cursor.getString(cursor
.getColumnIndex("data2"));
if (data2.equals("1")) {
// Family seat number
myc.setPhone_home(data1);
} else if (data2.equals("2")) {
// Cell-phone number
myc.setPhone_mobile(data1);
}
}
}
list.add(myc);
Log.i("oye", "*************************************");
}
return list;
}
Reading mode 2:
public void queryAllMethod2() {
// Manage Uri of all contacts
Cursor c1 = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null,
null, null);
//Read the names of all contacts
while (c1.moveToNext()) {
String name = c1.getString(c1
.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Log.i("oye", "c1 ddd " + c1.toString() + " " + name);
}
Cursor c2 = cr.query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null,
null, null);
//Read the phone numbers of all contacts
while (c2.moveToNext()) {
String number = c2.getString(c2
.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
Log.i("oye", "c1 ddd " + c2.toString() + " " + number);
}
}
Permissions that need to be added:
<! - Access to Address Book Contacts - > <uses-permission android:name="android.permission.READ_CONTACTS"/> <! - Modify and add the permissions of contacts in the address book - >. <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
How to delete data:
case R.id.but_delete:
//Delete Contacts in Address Book
//1. Delete data from raw_contacts table
cr.delete(Uri.parse("content://com.android.contacts/raw_contacts"), "_id=2", null);
//2. (Not to write) Remove contacts from the data table
cr.delete(Uri.parse("content://com.android.contacts/data"), "raw_contact_id = 2", null);
break;
How to add new data:
case R.id.but_insert:
//Additional Contact Data
//1.First direction raw_contacts Save the data in the table and get the corresponding newly added data id value
ContentValues values = new ContentValues();
values.put("display_name", "Xiao Zhao");
Uri uri = cr.insert(Uri.parse("content://com.android.contacts/raw_contacts"), values);
//Get the id value corresponding to the newly added data
String id = uri.getLastPathSegment();
//2. according to id towards data Information stored in the table, name, mailbox and telephone number
//Deposit name information
values.clear();
values.put("data1", "Xiao Zhao");
values.put("raw_contact_id", id);
values.put("mimetype", "vnd.android.cursor.item/name");
cr.insert(Uri.parse("content://com.android.contacts/data"), values);
//Mailbox information
values.clear();
values.put("data1", "250@250.com");
values.put("raw_contact_id", id);
values.put("mimetype", "vnd.android.cursor.item/email_v2");
values.put("data2", "1");
cr.insert(Uri.parse("content://com.android.contacts/data"), values);
//Store telephone number information
values.clear();
values.put("data1", "250250250");
values.put("raw_contact_id", id);
values.put("mimetype", "vnd.android.cursor.item/phone_v2");
values.put("data2", "2");
cr.insert(Uri.parse("content://com.android.contacts/data"), values);
break;
How to modify data:
case R.id.but_update:
//Modify contacts
//Modify the original content in the database
ContentValues values2 = new ContentValues();
values2.put("data1", "252252252");
cr.update(Uri.parse("content://com.android.contacts/data"), values2, "raw_contact_id = ? and mimetype = ?", new String[]{"3","vnd.android.cursor.item/phone_v2"});
//Add new content to the database
ContentValues values1 = new ContentValues();
values1.put("data1", "Family address:");
values1.put("raw_contact_id", 3);
values1.put("mimetype", "vnd.android.cursor.item/postal-address_v2");
cr.insert(Uri.parse("content://com.android.contacts/data"), values1);
break;