In the last study, the use of the original content provider Contact,contact has multi-layer mapping relationships, more complex, not as a good choice for small examples, in this study, we will learn how to build content Provider, and through the URI for the increase and deletion of the search. If the app's data needs to be used only for its own use, it does not require content provider, and instead avoids doing so, allowing direct access to the data, but creating content provider is a regular tool if you want the data to be accessible by other apps .
On the URI of content provider
In the last study, we talked about the format of the URI. Now it has been content://com.wei.android.myproject/card/pin/17 as an example, concrete deconstruction.
1, Scheme part: content://, indicating that this is a content URI, rather than an http://network URI;
2, authority (COM.WEI.ANDRIOD.MYPROJECT) follow the scheme part, is the only identity, usually we use the class of namespace naming method, indicating attribution.
3, after authority (Com.wei.android.myproject), before instance identifier (17), used to indicate the path, the type of content, that is, "Card/pin" in the example, this part can be empty.
4, the last is instance identifier, is an integer that indicates the specific location of the data in the content. The URI of a content, if not instance identifier, represents the data set (collection) of the content.
The data that the URI points to in the content has the corresponding MIME type pair, one for collection and one for instance. For collection,mime type should be Vnd.x.cursor.dir/y,x is the name of our company, organization or project, and Y is used "." Segmentation. such as Vnd.wei.cursor.dir/com.wei.android.myproject.card.pin. For instance, the MIME type should be vnd.x.cursor.item/y, where X and Y are consistent with collection.
Create a content provider: Create your own provider class
Provide our own subclasses by inheriting ContentProvider. We will use SQLite way, in the Android learning Note (41): The use of SQLite learning, a lot of code can be reused. We will encapsulate SQLite's data provider through content provider, allowing other apps to access data through URIs.
Step 1: Create your own provider class, you need to override the 6 abstract methods OnCreate (), query (), insert (), update (), delete (), and return the MIME type of GetType (). Because a content provider allows multiple clients to access at the same time, client a modifies the data (Insert,update,delete) and notifies other queries of the client (query) so that other clients can synchronize the data. See Example Blue section. For SQLite, some templates can be applied, see the Green section.
Step 2: Set the URI and the properties of the provider , see the example dark red Word section.
//Step 1: Create your own provider class by inheriting ContentProvider, you need to override 6 abstract methods for creating, reading, updating, and deleting
Public class Gravityprovider extends ContentProvider{
Private String db_name = "gravity.db";
public static final String table= "constants";
Private Sqlitedatabase db = null;
/* Step 2: Define the URI and the properties of the provider */
/ * Step 2.1 by inheriting the static public class description of the Basecolumns, declaring the URI, and the basic properties so that the client is with OH that. If the information store is in SQLite, these properties generalists are the column of the table, so that we can easily pass the information in the Update,insert. The type of the property does not have a specific requirement, as long as the cursor can support it. The basecolummns already contains id=_id * /
Public Static Final class Constants implements Basecolumns {
/ * Step 2.2 defines the URI, which provides the URI for each collection of the content provider, in order to avoid URI collisions, it can be using the Java class namespace */
public static final UriContent_uri= Uri.parse ("content://" + Authority + "/gravity");
/ * Step 2.3 defines some basic properties, for SQLite is the name of column * /
public static final String title= "TITLE";
public static final String value= "VALUE";
}
public static final String authority = "Com.wei.android.learning.provider";
//"Generic template Class" establishes a tree-like hierarchy of URIs to facilitate checking for URI matching: Iscollecturi ()
private static final Urimatcher Surimatcher = new Urimatcher (urimatcher.no_match);
private static final int CONSTANTS = 1;
private static final int constants_id = 2;
static {
/ /For specific instance, actually add/<num> after collection, for example .../1, with # for numbers
Surimatcher.adduri (Authority, "Gravity", CONSTANTS);
Surimatcher.adduri (Authority, "gravity/#", constants_id);
}
//"Generic template class" sets the map for the query map, which is helpful for SQLite to rename the column by using the column name passed by query and alluding to the specific database column name.
private static hashmap<string,string> Constants_list_project = new hashmap<string, string> ();
static{
Constants_list_project.put (gravityprovider.constants._id, gravityprovider.constants._id);
Constants_list_project.put (GravityProvider.Constants.TITLE, GravityProvider.Constants.TITLE);
Constants_list_project.put (GravityProvider.Constants.VALUE, GravityProvider.Constants.VALUE);
}
/* Step 1.1:oncreate () is the entry for ContentProvider, which is used for initialization processing. If the data is a file format, it detects the file path and whether the file exists, creates it if it does not exist, and establishes a SQLite association for SQLite. If you update the data structure in ContentProvider, you should check whether the old and new data structures are compatible. OnCreate () is the entrance to the general beginning of the content provider, or the release of the update * /
Public Boolean onCreate (){
db= (New Gravitydbhelper (GetContext ())). Getwritabledatabase ();
return (db = = null)? False:true;
}
/* Step 1.2: Process the query, which corresponds to the Managequery query that handles the client and returns the cursor. These parameters are particularly suitable for storing data in SQLite mode, and we can omit certain parameters, such as returning data based only on a URI, which should be described in the doc description of the method. */
Public Cursor query (Uri uri, string[] projection, string selection, string[] Selectionargs, string sortOrder){
//For SQLite, use Sqlitequerybuilder to put parameters into an SQL statement, as follows:
sqlitequerybuilder QB = new Sqlitequerybuilder ();
Qb.Settables(Gettablename ());
if (Iscollectionuri (URI)) {
//If it is a URI of collection, this example is Content://com.wei.android.learning/constants, set the returned content, and use the structure of the HashMap to map to the content Provider in the package.
Qb.setprojectionmap (Constants_list_project);
}else{
//If it is the ID of instance, this example is content://com.wei.android.learning/constants/#, that is, the user who needs to query a specific _id, so add the Where condition description
Qb.Appendwhere(gravityprovider.constants._id + "=" + uri.getpathsegments (). Get (1));
}
//Get sort by, or give the sorting method of the vacancy province
String by = null;
if (Textutils.isempty (SortOrder)) {
Orderby= Getdefaultsortorder ();
}else{
= SortOrder;
}
//Find database, get cursor
Cursor c=qb.query (db, Projection, selection, Selectionargs, NULL, NULL, by-and-by);
//"Registration notification" notifies the client when the data corresponding to the URI has changed. Content providers can have multiple apps (clients) to access, providing notifications of synchronized data.
C.setnotificationuri (GetContext (). Getcontentresolver (), URI);
return C;
}
/* Step 1.3 Insert () processing adds data, where parameter 1: The URI that represents collection, Parameter 2: is the content of instance, and returns a instance URI */
Public uri Insert (URI uri, contentvalues values){
Long rowId;
Contentvalues CV = null;
if (values! = null) {
CV = new Contentvalues (values);
}else{
CV = new Contentvalues (); Empty inserts may be allowed, so null is not necessarily an exception
}
//Detect if URI is valid: if instance URI, not collection Uri, cannot increase URI, throw exception
if (!iscollectionuri (URI)) {
throw new IllegalArgumentException ("Unknown uri" + uri);
}
//Detect whether the supplied data is complete: The required columns is present or throws an exception
For (String colname:getrequiredcolumns ()) {
if (!cv.containskey (colname)) {
throw new IllegalArgumentException ("Miss column:" + colname);
}
}
//Fill in the default value for the non-essential column of the vacancy
Populardefaultvalues (CV);
RowId =Db.insert (Gettablename (), Getnullcolumnhack (), CV);
if (RowId > 0) {
Uri Instanceuri = Contenturis.withappendedid (Getcontenturi (), rowId);
"Notification of registered client data changes" occurs when the URI points to a data change and notifies all registrants that an update has occurred through Notifychange (). The second parameter of this example is NULL, if not NULL, indicating that the change is caused by the oberver without notifying the Observer
GetContext (). Getcontentresolver (). Notifychange (Instanceuri, NULL);
return Instanceuri;
}
return null;
}
/* Step 1.4: Used to modify the value of one or more instance, usually only for sqlite, no person generally ignored. */
public int update (URI uri, contentvalues values, String selection, string[] Selectionargs) {
int count = 0;
if (Iscollectionuri (URI)) {
Count = db.Update(Gettablename (), values, selection, Selectionargs);
}else{//If it is instance, make an ID in the where
String segment = Uri.getpathsegments (). get (1);
Count = db.Update(Gettablename (), Values,
Getidcolumnname () + "=" + Segment + (Textutils.isempty (selection)? "": "and (" + Selection + ")"),
Selectionargs);
}
GetContext (). Getcontentresolver ().Notifychange(URI, null);//"Notification registration client data changes"
return count;
}
/* Step 1.5: Process Delete */
public int Delete (URI Uri, String selection, string[] Selectionargs) {
int count = 0;
if (Iscollectionuri (URI)) {
Count = db.Delete(Gettablename (), selection, Selectionargs);
}else{
String segment = Uri.getpathsegments (). get (1);
Count = db.Delete(Gettablename (),
Getidcolumnname () + "=" +segment + (Textutils.isempty (selection)? "": "and (" + Selection + ")"),
Selectionargs);
}
GetContext (). Getcontentresolver (). Notifychange (URI, NULL);//"Notify registered client data changes"
return count;
}
/* Step 1.6 returns the MIME Type of collection or instance */
Public String GetType (Uri uri) {
if (Iscollectionuri (URI)) {
return Getcollectiontype ();
}else{
return Getinstancetype ();
}
}
//"Generic template class" for SQLite content provider's processing, there are already routines, the following can be used as a templated processing
Private string[]Getrequiredcolumns(){
Return (new String[]{constants.title});
}
private voidpopulardefaultvalues(Contentvalues values) {
if (!values.containskey (Constants.value))
Values.put (Constants.value, 0.0f);
}
Private UriGetcontenturi(){
return Constants.content_uri;
}
Private StringGetidcolumnname(){
return constants._id;
}
Private StringGettablename(){
return gravityprovider.table;
}
Private BooleanIscollectionuri(URI Uri) {
Return Surimatcher.match (uri) = = CONSTANTS;
}
Private StringGetdefaultsortorder(){
return GravityProvider.Constants.TITLE;
}
Private StringGetnullcolumnhack(){
return GravityProvider.Constants.TITLE;
}
Returns the MIME type of collection
Private StringGetcollectiontype(){
return "Vnd.wei.cursor.dir/com.wei.android.learning.gravity";
}
Returns the MIME type of instance
Private StringGetinstancetype(){
return "Vnd.wei.cursor.item/com.wei.android.learning.gravity";
}
/* Below this section is to create SQLite, we directly use the Andriod learning Note (41) example, the code is not duplicated */
Private class Gravitydbhelper extends Sqliteopenhelper{
...... ......
}
}
Step three: Declare provider in Androidmanifest.xml, allowing the application defined in the XML to use the content provider's data provider. As follows. If there are multiple authortity, and all are listed.
<provider Android:name= ". Gravityprovider " android:authorities=" Com.wei.android.learning.provider "/>
Android Learning Note (48): Provide your own content Provider