Content Provider is primarily used to share data between different applications, although both the file storage and Sharepreferences provided by Android can be set to share data in global read-write mode, but due to security issues, has been abandoned in the Android4.2. The content provider provides a secure way to share data. When a program provides an external access interface through a content provider, any other program can access this data through the interface, for example: contact data, SMS data.
I. Accessing data in other applications
1. Get an instance of the Contentresolver class
For each application, if you want to access the data in the content provider, you have to use the Contentresolver class to get an instance of the class through the Getcontentresolver () method in the context.
The Contentresolver class provides methods such as insert (), delete (), update (), and query () similar to SQLite to implement additions and deletions to the data, but the parameters are slightly different from those in SQLite.
Note: The method of adding and deleting in contentresolver does not accept the table name parameter, but instead uses the URI parameter , which is called the content URI.
2. Get content URI
The content URI establishes a unique identifier for the parameter in the content provider, which is composed primarily of permissions and paths , and the permissions are primarily used to distinguish between different applications, typically using the package name. For example: Com.example.app.provider. A path is a distinction between different tables in the same application, followed by the/+ of the table name. Finally, I'm hungry. A protocol statement is required to form the full content URI.
Content URI standard format
content://com.example.app.provider/table1content://com.example.app.provider/table2
3. Resolves a URI string to a URI object
Uri uri = Uri.parse("content://com.example.app.provider/table1");
4. Data to be increased and censored
//Insert DataContentvalues values1 =NewContentvalues (); Values1.put ("Column1","Text1"); Values1.put ("Column2","Text2"); Getcontentresolver (). Insert (URI, values1);//Delete dataGetcontentresolver (). Delete (URI,"cloumn2=?",New String[]{"1"});//Modify DataContentvalues Values2 =NewContentvalues (); Values2.put ("Column1","T"); Getcontentresolver (). Update (URI, Values2,"Column1 =?" and column2=? ",New String[]{"Text","1"});//Query datacursor cursor = getcontentresolver (). Query (URI, projection, selection, Selectionargs, SortOrder);if(Cursor! =NULL){ while(Cursor.movetonext ()) {StringColumn1 = cursor.getstring (Cursor.getcolumnindex ("Column1")); int column2 = Cursor.getint (Cursor.getcolumnindex ("Column2")); } cursor.close ();}
The above operation is very similar to SQLite, except that the passed parameter is no longer a table name, but rather a parsed URI object.
The following highlights the meaning of each parameter in query ()
Query Method Parameters |
corresponding SQL section |
Description |
Uri |
From table_name |
Specify a table under the application you want to query |
Projection |
Select Column1,column2 |
Specify the column name of the query |
Selection |
where Column=value |
Specify the WHERE constraint |
Selectionargs |
- |
Provide a specific value for a placeholder in the where |
By |
ORDER BY Column1,column2 |
Specify how query results are sorted |
Here's a small example of getting contact information
MainActivity.java中的代码
Public class mainactivity extends appcompatactivity { PrivateListView Contactsview;PrivateArrayadapter<string> adapter;PrivateList<string> contactslist =NewArraylist<> ();@Override protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate); Setcontentview (R.layout.activity_main); Contactsview = (ListView) Findviewbyid (R.id.contacts_view); adapter =NewArrayadapter<string> ( ThisAndroid. R.layout.simple_list_item_1, contactslist); Contactsview.setadapter (adapter); Readcontacts (); }Private void readcontacts() {CURSOR cursor =NULL;Try{//Query contact Datacursor = Getcontentresolver (). Query (ContactsContract.CommonDataKinds.Phone.CONTENT_URI,NULL,NULL,NULL,NULL); while(Cursor.movetonext ()) {//Get Contact nameString displayName = cursor.getstring (Cursor.getcolumnindex (ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)) ;//Get contact phone numberString number = cursor.getstring (Cursor.getcolumnindex (ContactsContract.CommonDataKinds.Phone.NUMBER)); Contactslist.add (DisplayName +"\ n"+ number); } }Catch(Exception e) {E.printstacktrace (); }finally{if(Cursor! =NULL) {cursor.close (); } } }}
activity_main.xml文件
<?xml version= "1.0" encoding= "Utf-8"?><linearlayoutxmlns:android="Http://schemas.android.com/apk/res/android" Android:layout_width="Match_parent"android:layout_height="Match_parent"> <ListViewandroid:id="@+id/contacts_view"android:layout_width= "Match_parent" android:layout_height="Match_parent"android:text="Hello world!" / > </linearlayout>
The URI object in the above code is not parsed by the parse () method, because the official provides us with the parsed URI object directly. When we get the phone contact name and phone number, we simply display it in the ListView.
Second, create your own content provider
Above we use the content provider provided by others to get the data shared by other programs, we will create our own content provider to share the data in our own application. Here are the basic steps
1. Create a class to inherit ContentProvider, overriding 6 of these abstract methods.
Here's a quick introduction to these 6 methods (similar to the one in SQLite)
1. OnCreate () is called when the content provider is initialized ——-. This is where you typically complete database creation or upgrade operations. Returns true to indicate that the content provider was initialized successfully and that false indicates failure.
Note: The content provider is initialized only when there are contentresolver trying to access data in our program.
2. Query () -queries the data from the content provider, and the parameters of the query method are described in detail in the table above.
3. Insert () -Adds a piece of data to the content provider, which is already described in the code above.
4. Update () -Updates the data already in the content provider.
5. Delete ()- delete data from the content provider
6. GetType () -Returns the MIME type of the response based on the URI passed in.
2. Parses the content URI.
The standard content URI (end of Path, which indicates that all data in the table is expected to be accessed):
content://com.example.app.provider/table
Content URI with ID (ending with ID, indicating access to data with the corresponding ID in the table):
content://com.example.app.provider/table/1
In order to parse the two content URIs in the next step, we must also use wildcards to match the above two patterns.
1. * ——-means match any character of any length
2. # ——-means matching numbers of any length
//匹配上面第一行内容URI(所有数据)content://com.example.app.provider/table/*//匹配上面第二种URI(相应id的数据)content://com.example.app.provider/table/#
3. The matching content URI is implemented with the help of the Urimatcher class.
We have analyzed the content URI above, and then we use the Adduri () method provided by the Urimatcher class to pass in sequentially three parameters (permissions, paths, custom code (identity)). Finally we call Urimatcher's match () method , passing in a URI object, returning the custom code (identity) We just passed in, which we use to determine the intent of the caller to access the data.
Public class MyProvider extends contentprovider { //Custom code Public Static Final intTable1_dir =0; Public Static Final intTable1_item =1;Private StaticUrimatcher Urimatcher;Static{Urimatcher =NewUrimatcher (Urimatcher.no_match);//Expect to query all dataUrimatcher.adduri ("Com.example.app.provider","Table1", Table1_dir);//Expect data to be queried for the corresponding IDUrimatcher.adduri ("Com.example.app.provider","table1/#", Table1_item); }@Nullable @Override PublicCursorQuery(Uri Uri, string[] strings, string s, string[] strings1, string s1) {Switch(Urimatcher.match (URI)) { CaseTable1_dir://Query all data Break; CaseTable1_item://Query single data Break;default: Break; }return NULL; }}
The above code simply demonstrates the override in the query () method, which is similar to the overrides in Insert (), update (), delete (), and the custom code from the URI object, with the intent to write the appropriate logic after the user accesses the data.
4. Override the GetType () method.
The
GetType () method is a method that all content providers must provide to get the MIME type for the URI object, and a content URI that corresponds to a MIME type string that consists of three parts. Android does the following:
1. Must start with VND
2. If the content URI ends with a path, it is followed by android.cursor.dir/, If the content URI ends with an ID, it is followed by android.cursor.item/
3. Last access to vnd.< permissions >.< path;
//content uri with path end Vnd.android .cursor .dir /vnd.com .example .app .provider .table 1//content URI end with ID vnd.android Span class= "Hljs-preprocessor" >.cursor .item /vnd.com .example .provider .table 1
@Nullable@OverridepublicgetType(Uri uri) { switch (uriMatcher.match(uri)){ case TABLE1_DIR: return"vnd.android.cursor.dir/vnd.com.example.app.provider.table1"; case TABLE1_ITEM: return"vnd.android.cursor.item/vnd.com.example.app.provider.table1"; } returnnull;}
From the above, we will also find that the content provider can guarantee the security of the data, because in order to make the data to be added and checked, we first need to match to the content URI format, as long as we do not add private data into the Urimatcher, our privacy data will not be accessed.
Android Component----content provider Provider