ContentProvider Summary (Android), androidprovider
ContentProvider
1. Applicable scenarios
1) ContentProvider provides a unified interface for data storage and reading.
2) using ContentProvider, applications can share data
3) Many of the android built-in data is in the ContentProvider format for developers to call (such as video, audio, image, Address Book, etc)
2. Introduction to related concepts
1) ContentProvider Introduction
When an application inherits the ContentProvider class and overwrites the class to provide and store data, it can share its data with other applications. Although data can be shared externally by using other methods, the data access method varies depending on the data storage method. For example, if data is shared externally by using the file method, you need to perform file operations to read and write data; to use sharedpreferences to share data, you must use the sharedpreferences API to read and write data. The advantage of using ContentProvider to share data is to unify the data access mode.
2) Uri class Introduction
Uri uri = Uri. parse ("content: // com. changcheng. provider. contactprovider/contact ")
The query strings used in Content providers are different from standard SQL queries. We use a special URI for many operations such as select, add, delete, and modify. This URI consists of three parts: "content ://", indicates the data path and an optional ID. The following is an example URI:
Content: // media/internal/images this URI will return all images stored on the device
Content: // contacts/people/This URI will return all contacts on the device.
Content: // contacts/people/45 This URI returns a single result (the contact record with ID 45 in the contact information)
Although this query string format is common, it looks a bit confusing. Therefore, Android provides a series of help classes (in android. under the provider package), which contains a lot of query strings in the form of class variables, this method is easier for us to understand, so, as shown in the above content: // The contacts/people/45 URI can be written as follows:
Uri person = ContentUris. withAppendedId (People. CONTENT_URI, 45 );
Then execute the Data Query:
Cursor cur = managedQuery (person, null );
This query returns a cursor containing all data fields. We can use this cursor to retrieve all data:
Package com. wissen. testApp; public class ContentProviderDemo extends Activity {@ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); displayRecords ();} private void displayRecords () {// This array contains all the fields to return: String columns [] = new String [] {People. NAME, People. NUMBER}; Uri mContacts = People. CONTENT_URI; Cursor cur = managedQuery (mContacts, columns, // null data field to be returned, // null in the WHERE clause, and null in the WHERE clause // Order-by clause ); if (cur. moveToFirst () {String name = null; String phoneNo = null; do {// obtain the field value name = cur. getString (cur. getColumnIndex (People. NAME); phoneNo = cur. getString (cur. getColumnIndex (People. NUMBER); Toast. makeText (this, name + "+ phoneNo, Toast. LENGTH_LONG ). show () ;}while (cur. moveToNext ());}}}
The preceding example shows how to read the specified data column name and number in the contact information table in sequence.
Modification record:
We can use the ContentResolver. update () method to modify the data. Let's write a method to modify the data:
private void updateRecord(int recNo, String name) { Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, recNo); ContentValues values = new ContentValues(); values.put(People.NAME, name); getContentResolver().update(uri, values, null, null);}
Now you can call the above method to update the specified record:
UpdateRecord (10, "XYZ"); // change the name field value of the first record to "XYZ"
Add record:
To add records, we can call ContentResolver. insert () method. This method accepts the target URI of the record to be added and a Map object containing the value of the new record. The returned value after the call is the URI of the new record, including the record number.
In the above example, we are all based on the standard Content Provider of the contact information book. Now we will create an insertRecord () method to add data to the contact information book:
private void insertRecords(String name, String phoneNo) { ContentValues values = new ContentValues(); values.put(People.NAME, name); Uri uri = getContentResolver().insert(People.CONTENT_URI, values); Log.d(”ANDROID”, uri.toString()); Uri numberUri = Uri.withAppendedPath(uri, People.Phones.CONTENT_DIRECTORY); values.clear(); values.put(Contacts.Phones.TYPE, People.Phones.TYPE_MOBILE); values.put(People.NUMBER, phoneNo); getContentResolver().insert(numberUri, values);}
In this way, you can call insertRecords (name, phoneNo) to add the contact name and phone number to the contact information book.
Delete record:
The getContextResolver. delete () method in Content Provider can be used to delete records. The following records are used to delete all contact information on the device:
private void deleteRecords() { Uri uri = People.CONTENT_URI; getContentResolver().delete(uri, null, null);}
You can also specify the WHERE Condition Statement to delete a specific record:
GetContentResolver (). delete (uri, "NAME =" + "'xyz XYZ '", null );
This will delete the record whose name is 'xyz xyz.
3. Create ContentProvider
To create our own Content Provider, follow these steps:
A. Create a class that inherits the ContentProvider parent class
B. define a class variable named CONTENT_URI and public static final Uri. You must specify a unique string value for it. The best solution is to use the full name of the class, such:
Public static final Uri CONTENT_URI = Uri. parse ("content: // com. google. android. MyContentProvider ");
C. Define the data column name you want to return to the client. If you are using the Android database, you must define a column named _ id for it to indicate the uniqueness of each record.
D. Create your data storage system. Most Content providers use the Android file system or SQLite database to maintain data, but you can store the data in any way you want.
E. If you want to store byte data, such as bitmap files, the data column is actually a URI string that represents the actually saved file and uses it to read the corresponding file data. To process this data type, the Content Provider needs to implement a field named _ data, And the _ data field lists the precise paths of the file on the Android file system. This field is not only used by the client, but also for ContentResolver. The client can call ContentResolver. the openOutputStream () method is used to process the file Resources pointed to by the URI. If it is ContentResolver itself, it can directly access the data file because it has higher permissions than the client.
F. Declare a public static String variable to specify the data column to be returned from the cursor.
G. The query returns a Cursor type object. All write operations, such as insert (), update (), and delete (), will be monitored. We can use the ContentResover (). policychange () method to notify the listener about data updates.
H. Use the <provider> label in AndroidMenifest. xml to set the Content Provider.
I. If the data type you want to process is a relatively new type, you must first define a new MIME type for ContentProvider. geType (url) to return. The MIME type can be either specified for a single record or multiple records. A common format is provided here:
Vnd. android. cursor. item/vnd. yourcompanyname. contenttype (MIME type of a single record)
For example, a request for train information URI such as content: // com. example. transportationprovider/trains/122 may return typevnd. android. cursor. item/vnd. example. a mime type such as rail.
Vnd. android. cursor. dir/vnd. yourcompanyname. contenttype (MIME type of multiple Records)
For example, a URI that requests all train information, such as content: // com. example. transportationprovider/trains may return vnd. android. cursor. dir/vnd. example. a mime type such as rail.
The following code creates a Content Provider that only stores the user name and displays all the user names (using the SQLLite database to store the data ):
Public class MyUsers {public static final String AUTHORITY = "com. wissen. myContentProvider "; // The BaseColumn class already contains the _ id field public static final class User implements BaseColumns {public static final Uri CONTENT_URI = Uri. parse ("content: // com. wissen. myContentProvider "); // table data column public static final String USER_NAME =" USER_NAME ";}}
The class above defines the Content Provider's CONTENT_URI and data columns. The following defines the actual Content Provider class based on the above class:
Public class MyContentProvider extends ContentProvider {private SQLiteDatabase sqlDB; private DatabaseHelper dbHelper; private static final String DATABASE_NAME = "Users. db "; private static final int DATABASE_VERSION = 1; private static final String TABLE_NAME =" User "; private static final String TAG =" MyContentProvider "; private static class DatabaseHelper extends SQLiteOpenHelper {DatabaseHelpe R (Context context) {super (context, DATABASE_NAME, null, DATABASE_VERSION) ;}@ Override public void onCreate (SQLiteDatabase db) {// Create the table db.exe cSQL ("Create table" + TABLE_NAME + "(_ id integer primary key autoincrement, USER_NAME TEXT);") used to store data );");} @ Override public void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion) {db.exe cSQL ("drop table if exists" + TABLE_NAME); onCreate (db );}} @ Override public int delete (Uri uri, String s, String [] as) {return 0 ;}@ Override public String getType (Uri uri) {return null ;} @ Override public Uri insert (Uri uri, ContentValues contentvalues) {sqlDB = dbHelper. getWritableDatabase (); long rowId = sqlDB. insert (TABLE_NAME, "", contentvalues); if (rowId> 0) {Uri rowUri = ContentUris. appendId (MyUsers. user. CONTENT_URI.buildUpon (), rowId ). buil D (); getContext (). getContentResolver (). notifyChange (rowUri, null); return rowUri;} throw new SQLException ("Failed to insert row into" + uri);} @ Override public boolean onCreate () {dbHelper = new DatabaseHelper (getContext (); return (dbHelper = null )? False: true;} @ Override public Cursor query (Uri uri, String [] projection, String selection, String [] selectionArgs, String sortOrder) {SQLiteQueryBuilder qb = new SQLiteQueryBuilder (); SQLiteDatabase db = dbHelper. getReadableDatabase (); qb. setTables (TABLE_NAME); Cursor c = qb. query (db, projection, selection, null, sortOrder); c. setNotificationUri (getContext (). getContentResolver (), uri); return c ;}@ Override public int update (Uri uri, ContentValues contentvalues, String s, String [] as) {return 0 ;}}
A Content Provider named MyContentProvider is created and used to add and read records from the Sqlite database.
The Content Provider entry must be configured in AndroidManifest. xml:
<provider android:name=”MyContentProvider” android:authorities=”com.wissen.MyContentProvider” />
Then, let's use the defined Content Provider:
1) Add the ContentProvider access permission to the application.
2) use the getContentResolver () method to obtain the ContentResolver object.
3) Call the ContentResolver class query () method to query data. This method returns a Cursor object.
4) analyze the obtained Cursor object to obtain the required data.
5) Call the close () method of the Cursor class to close the Cursor object.
public class MyContentDemo extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); insertRecord(”MyUser”); displayRecords(); } private void insertRecord(String userName) { ContentValues values = new ContentValues(); values.put(MyUsers.User.USER_NAME, userName); getContentResolver().insert(MyUsers.User.CONTENT_URI, values); } private void displayRecords() { String columns[] = new String[] { MyUsers.User._ID, MyUsers.User.USER_NAME }; Uri myUri = MyUsers.User.CONTENT_URI; Cursor cur = managedQuery(myUri, columns,null, null, null ); if (cur.moveToFirst()) { String id = null; String userName = null; do { id = cur.getString(cur.getColumnIndex(MyUsers.User._ID)); userName = cur.getString(cur.getColumnIndex(MyUsers.User.USER_NAME)); Toast.makeText(this, id + ” ” + userName, Toast.LENGTH_LONG).show(); } while (cur.moveToNext()); } }}
How to Use ContentProvider in Android to read system files
I have a code for reading the email address in the address book. As for reading the phone number, it is similar:
Private ArrayList <String> getEmailAddress (){
EmailAddress = new ArrayList <String> ();
Cursor c = getContentResolver ()
. Query (
ContactsContract. Data. CONTENT_URI, null, Data. MIMETYPE
+ "= '"
+ ContactsContract. CommonDataKinds. Email. CONTENT_ITEM_TYPE
+ "'", Null, null );
If (c. getCount ()> 0 ){
While (c. moveToNext ()){
Int mailindex = c. getColumnIndex (Data. DATA1 );
String mail = c. getString (mailindex );
Log. v ("minetype", mail );
EmailAddress. add (mail );
}
}
C. close ();
Return emailAddress;
}
In addition, add the following to AndroidManifest. xml:
<Uses-permission android: name = "android. permission. READ_CONTACTS"/> to read the address book. Of course, this is not the case if you want to read the phone book. Check the api by yourself!
Android ContentProvider Problems
The role of ContentProvider in android is to share data externally, that is, you can share the data in the application to other applications through ContentProvider for access. Other applications can use ContentProvider to add, delete, modify, and query data in your application. For data sharing, we have learned the file operation mode before. We know that the operation mode of a specified file is Context. MODE_WORLD_READABLE or Context. MODE_WORLD_WRITEABLE. So why use ContentProvider to share data externally? If the file operation mode is used to share data externally, the Data Access Mode varies depending on the data storage mode, resulting in inconsistent data access methods, such: if an xml file is used to share data, xml parsing is required to read data. If sharedpreferences is used to share data, the sharedpreferences API must be used to read data.
The advantage of using ContentProvider to share data externally is to unify the data access mode.
When an application needs to share data externally through ContentProvider, the first step is to inherit ContentProvider and override the following method:
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 second step must be in AndroidManifest. xml uses <provider> to configure the ContentProvider. To allow other applications to find the ContentProvider, The ContentProvider uses authorities (host name/Domain Name) to uniquely identify it, you can regard ContentProvider as a website (think about it, the website also provides data), and authorities is its domain name:
<Manifest...>
<Application android: icon = "@ drawable/icon" android: label = "@ string/app_name">
<Provider android: name = ". PersonContentProvider" android: authorities = "cn. ccy. providers. personprovider"/>
</Application>
</Manifest>
I just mentioned through application A directly... the remaining full text>