Android Learning Notes (48): Provide your own content Provider

Source: Internet
Author: User
Tags data structures sqlite throw exception

In the last study, the use of the original content provider Contact,contact has a multi-level mapping relationship, more complex, not as a good choice for small examples, in this study, we will learn how to create content Provider, and through the URI of the increase and deletion check. If the applied data is only for its own use and does not require content provider, instead of doing so, you can access the data directly, but if you want the data to be accessed by other applications, creating the content provider is the usual method .

again on the URI of content provider

In the last study, we talked about the format of the URI. It has now been content://com.wei.android.myproject/card/pin/17 as an example of concrete deconstruction.

1, Scheme section: content://, indicating that this is a content of the URI, rather than a http://network URI;

2, authority (COM.WEI.ANDRIOD.MYPROJECT) followed the scheme part, is the only identification, usually we use the class of the namespace naming method, indicating attribution.

3, after authority (Com.wei.android.myproject), before the instance identifier (17), used to indicate the path, the type of the content, that is, "Card/pin" in the example, this part can be empty.

4, the last is instance identifier, is an integer, indicating the exact location of the data in the content. The URI of a content, if there is no 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. The collection,mime type should be Vnd.x.cursor.dir/y,x is the name of our company, organization or project, and Y is using "." 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'll take a sqlite approach, learn from the Android learning notes (41): SQLite, a lot of code can be reused. We will encapsulate the SQLite data provider through the content provider, allowing other applications to access the data through URIs.

Step 1: Create your own provider class, you need to override 6 abstract methods OnCreate (), query (), insert (), update (), delete (), and return a MIME type of GetType (). Because of a content provider that allows multiple clients to access simultaneously, client a modifies data (Insert,update,delete) and notifies other query clients (query) so that other clients can synchronize data. See Example Blue section. For SQLite, some templates can be applied, see the Green part.

Step 2: Set the URI and provider properties, see the example Red Character section.

//Step 1: Create your own provider class by inheriting ContentProvider, and you need to rewrite 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 Provider properties * *
/ * Step 2.1 inherits Basecolumns's static public class descriptions, declares the URI, and the basic attributes so that the client is in the OH. If the information store is in a sqlite way, these attribute generalists are the column of the table, so that we can easily pass information in Update,insert. The type of the property has no specific requirements, as long as the cursor can support it. In the Basecolummns already contains id=_id * *
Public Static Final class Constants implements Basecolumns {
/* Step 2.2 defines the URI, providing the URI of each collection of the content provider, in order to avoid the conflict of URIs, it can be namespace with Java classes.
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";

The generic template class establishes a tree-like hierarchy of URIs to facilitate checking for the matching of URIs: 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, it is actually after collection plus/<num>, for example .../1, using # to represent numbers
Surimatcher.adduri (Authority, "Gravity", CONSTANTS);
Surimatcher.adduri (Authority, "gravity/#", constants_id);
}

The generic template class sets the map for query mapping, and for SQLite, the column name that is passed through query is mapped to the specific database column name, which is helpful in renaming the column.
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 ContentProvider entry for initialization processing. If the data is a file format, the file path is detected and the file exists, and if it does not exist, it is created, and for SQLite, a SQLite association is established. If the data structure in ContentProvider is updated, the new and old data structures should be checked for compatibility. OnCreate () is the entry of the content provider ordinary start, or is the release of the updated entry /
Public Boolean onCreate (){
db= (New Gravitydbhelper (GetContext ())). Getwritabledatabase ();
return (db = = null)? False:true;
}


/* Step 1.2: Process the query, which corresponds to the processing client's managequery query, and returns cursor. These parameters are particularly suitable for storing data in a sqlite manner, and we can omit certain parameters, such as returning data only based on URIs, which should be described in the doc's 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 collection URI, this example is content://com.wei.android.learning/constants, sets the returned content, uses HASHMAP structure, maps to content In the provider package.
Qb.setprojectionmap (Constants_list_project);
}else{
//If it is the ID of the instance, this example is content://com.wei.android.learning/constants/#, that is, you need to query a specific _id user, so increase the condition description of where
Qb.Appendwhere(gravityprovider.constants._id + "=" + uri.getpathsegments (). Get (1));
}
  //Get a sort of order, or give the vacancy province a sort of way
String by = null;
if (Textutils.isempty (SortOrder)) {
Orderby= Getdefaultsortorder ();
}else{
by = SortOrder;
}
//Lookup database, getting cursors
Cursor c=qb.query (db, Projection, selection, Selectionargs, NULL, NULL, by-by);
////"registration notice" to notify the client when the corresponding data in the URI changes. Content providers can have multiple applications (clients) to access, providing notification of synchronized data.
C.setnotificationuri (GetContext (). Getcontentresolver (), URI);
return C;
}

/* Step 1.3 Insert () processing adds data, where parameter 1: Collection uri, Parameter 2: is instance content, 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 (); May allow vacant inserts, so null conditions are not necessarily abnormal
}
//Detection URI is valid: if instance URI, not collection Uri, that is, cannot add URI, throw exception
if (!iscollectionuri (URI)) {
throw new IllegalArgumentException ("Unknown uri" + uri);
}
//Detect whether the provided data is complete: the necessary columns or not, or throw an exception
For (String colname:getrequiredcolumns ()) {
if (!cv.containskey (colname)) {
throw new IllegalArgumentException ("Miss column:" + colname);
}
}
//To fill in the default value of the non-essential columns of the vacancy
Populardefaultvalues (CV);
RowId =Db.insert (Gettablename (), Getnullcolumnhack (), CV);
if (RowId > 0) {
Uri Instanceuri = Contenturis.withappendedid (Getcontenturi (), rowId);
//"Notify registered Client data change" occurs when the URI points to the data change, and notifies all registered users by Notifychange () that an update has occurred. The second parameter of this example is NULL, if not NULL, indicating that if the change is caused by the oberver, you do not need to notify 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, or not for general neglect. */
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, place the ID in 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);//"Notify registered 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 collection or instance * *
Public String GetType (Uri uri) {
if (Iscollectionuri (URI)) {
return Getcollectiontype ();
}else{
return Getinstancetype ();
}
}

"Generic template Class" for the SQLite content provider's processing, has a routine, the following can be used as template 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";
}

/* The following section is an example of creating SQLite, which we use directly with Andriod learning notes (41), the code is not repeated * *
Private class Gravitydbhelper extends Sqliteopenhelper{
...... ......
}

}

Step three: Declare the provider in Androidmanifest.xml, allowing the application defined in the XML to use the content provider data access interface. As follows. If there are multiple authortity, list them all.

<provider Android:name= ". Gravityprovider " android:authorities=" Com.wei.android.learning.provider "/>


RELATED links: My Andriod development related articles

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.