Today we'll explain how to create and invoke your own contentprovider.
In the previous two articles, we talked about how to read and write contacts and short messages, I believe that we have a certain degree of understanding of the operation of ContentProvider. In some cases, in addition to operating contentprovider, we may need to create their own contentprovider to provide information-sharing services, which requires us to have a good grasp of contentprovider creation and use of skills. Let's Youbiaojili step-by-step through each of these steps.
Before we get to the formal demo, let's take a look at the following two knowledge points:
Authorized:
In Android, each contentprovider will register itself with a string similar to a domain name, and we become an authorization (authority). This uniquely identified string is the basis of a set of URIs that this contentprovider can provide to provide a shared service of information to the outside world.
The authorization is done in Androidmanifest.xml, and each contentprovider must be declared and authorized here in the following manner:
<provider android:name= ". Someprovider "
The <provider> above indicates that the provider of the ContentProvider is the "Someprovider" class and authorizes it, and the underlying URI of the authorization is "Com.your-company.someprovider". With this authorization information, the system can accurately locate the specific contentprovider so that visitors can obtain the specified information. This is similar to browsing the Web page, "Someprovider" is like a specific server, and "Com.your-company.someprovider" is like a registered domain name, I believe we are not unfamiliar with this concept, This association can then understand the role of ContentProvider authorization. (Note that in addition to the Android built-in application, third party programs should try to use the fully qualified authorization name in the above manner.) )
MIME type:
Just as the web site returns the MIME (Multipurpose Internet Mail Extensions, Multipurpose Internet Message Extensions) type for a given URL (this allows the browser to view the content with the correct program), ContentProvider is also responsible for returning the MIME type of the given URI. According to the MIME type specification, MIME types contain two parts: type and subtype. For example: Text/html,text/css,text/xml and so on.
Android also follows a similar convention to define MIME types.
For a single record, the MIME type is similar to the following:
Vnd.android.cursor.item/vnd.your-company.content-type
For a collection of records, the MIME type is similar to the following:
Vnd.android.cursor.dir/vnd.your-company.comtent-type
The VND indicates that these types and subtypes have non-standard, vendor-specific forms; Content-type can be determined according to ContentProvider functions, such as the ContentProvider of a diary can be a note, The ContentProvider of the schedule can be schedule, and so on.
Having learned the above two knowledge points, we will illustrate the specific process with the example.
We will create a contentprovider that records the person information, implement CRUD operations on person, and visitors can manipulate our contentprovider via the following path:
Visitors can manipulate the person collection by "[Base_uri]/persons", or you can manipulate a single person in the form of "[base_uri]/persons/#".
We need two steps to create a person's ContentProvider:
1. Create Personprovider class:
We need to inherit the ContentProvider class and implement the methods of OnCreate, query, INSERT, UPDATE, Delete, and GetType. The specific code is as follows:
Package com.scott.provider;
Import Android.content.ContentProvider;
Import Android.content.ContentUris;
Import android.content.ContentValues;
Import Android.content.UriMatcher;
Import Android.database.Cursor;
Import Android.database.sqlite.SQLiteDatabase;
Import Android.net.Uri;
public class Personprovider extends ContentProvider {private static final urimatcher Matcher;
Private DBHelper Helper;
Private Sqlitedatabase DB;
Private static final String authority = "Com.scott.provider.PersonProvider";
private static final int person_all = 0;
private static final int person_one = 1;
public static final String Content_Type = "Vnd.android.cursor.dir/vnd.scott.person";
public static final String Content_item_type = "Vnd.android.cursor.item/vnd.scott.person";
Re-check private static final Uri Notify_uri = Uri.parse ("content://" + Authority + "/persons") immediately after data change
static {Matcher = new Urimatcher (urimatcher.no_match);Matcher.adduri (Authority, "persons", Person_all); Matching records set Matcher.adduri (authority, "persons/#", Person_one);
Match a single record} @Override public boolean onCreate () {helper = new DBHelper (GetContext ());
return true;
@Override public String getType (URI uri) {int match = Matcher.match (URI);
Switch (match) {case Person_all:return content_type;
Case Person_one:return Content_item_type;
Default:throw new IllegalArgumentException ("Unknown uri:" + uri); @Override public Cursor query (URI uri, string[] projection, String selection, string[] Selectionargs, STR
ing sortOrder) {db = Helper.getreadabledatabase ();
int match = Matcher.match (URI);
Switch (match) {case person_all://doesn ' t need no code in my provider.
Break
Case Person_one:long _id = Contenturis.parseid (URI);
Selection = "_id =?"; Selectionargs = new String[]{strIng.valueof (_id)};
Break
Default:throw new IllegalArgumentException ("Unknown uri:" + uri);
Return to Db.query ("person", projection, selection, Selectionargs, NULL, NULL, sortOrder);
@Override public uri Insert (URI uri, contentvalues values) {int match = Matcher.match (URI);
if (match!= Person_all) {throw new IllegalArgumentException ("wrong uri:" + uri);
db = Helper.getwritabledatabase ();
if (values = = null) {values = new contentvalues ();
Values.put ("name", "No Name");
Values.put ("Age", "1");
Values.put ("info", "no info.");
Long rowId = Db.insert ("person", null, values);
if (RowId > 0) {notifydatachanged ();
Return Contenturis.withappendedid (URI, rowId);
return null; @Override public int Delete (URI Uri, String selection, string[] selectionargs) {db = Helper.getwritabledat
Abase (); int match = Matcher.match (URI);
Switch (match) {case person_all://doesn ' t need no code in my provider.
Break
Case Person_one:long _id = Contenturis.parseid (URI);
Selection = "_id =?";
Selectionargs = new string[]{string.valueof (_id)};
int count = Db.delete ("Person", selection, Selectionargs);
if (Count > 0) {notifydatachanged ();
return count; @Override public int update (URI uri, contentvalues values, String selection, string[] selectionargs) {db =
Helper.getwritabledatabase ();
int match = Matcher.match (URI);
Switch (match) {case person_all://doesn ' t need no code in my provider.
Break
Case Person_one:long _id = Contenturis.parseid (URI);
Selection = "_id =?";
Selectionargs = new string[]{string.valueof (_id)};
Break
Default:throw new IllegalArgumentException ("Unknown uri:" + uri); int count = db.update ("Person", Values, selection, Selectionargs);
if (Count > 0) {notifydatachanged ();
return count; //Notifies the specified URI data has changed private void Notifydatachanged () {getcontext (). Getcontentresolver (). Notifychange (Notify_uri
, null);
}
}
In the Personprovider, we have defined the authorized address as "Com.scott.provider.PersonProvider", and I believe we have some understanding in the front. Based on this authorization, we used a urimatcher to match its path, and the "[Base_uri]/persons" and "[base_uri]/persons/#" paths are described above, respectively, corresponding to the collection of records and the operation of individual records. In the query, insert, UPDATE, and Delete methods, we determine whether the URI is an action record collection or a single record based on the Urimatcher match result, thus taking a different approach. In the GetType method, we will return different MIME types based on matching results, this step is not missing, such as we in the query method is likely to be the entire collection of queries, it is possible to query a single record, then we return the cursor or collection type, or a single record, This is consistent with the MIME type returned by GetType, as if browsing a Web page, the specified URL returns the type of information, then the browser should receive the corresponding MIME type. In addition, we notice that the Notifydatachanged method is called in the Insert, update, and Delete methods in the above code, and the only step in this method is to notify the "[Base_uri]/persons" visitor, The data has changed and should be reloaded.
In our personprovider, we used the person, the DBHelper class, the code is as follows:
Package com.scott.provider;
public class Person {public int _id;
public String name;
public int age;
public String info;
Public person () {} public person (string name, int age, String info) {this.name = name;
This.age = age;
This.info = info;
} [Java] view plain copy package com.scott.provider;
Import Android.content.Context;
Import Android.database.sqlite.SQLiteDatabase;
Import Android.database.sqlite.SQLiteOpenHelper;
public class DBHelper extends Sqliteopenhelper {private static final String database_name = "PROVIDER.DB";
private static final int database_version = 1;
Public DBHelper {Super (context, database_name, NULL, database_version);
@Override public void OnCreate (Sqlitedatabase db) {String sql = ' CREATE TABLE IF not EXISTS person ' +
"(_id integer PRIMARY KEY autoincrement, name VARCHAR, age INTEGER, info TEXT)";
Db.execsql (SQL); } @OvErride public void Onupgrade (sqlitedatabase db, int oldversion, int newversion) {db.execsql ("DROP TABLE IF EXISTS
Person ");
OnCreate (DB);
}
}
Finally, in order for this contentprovider to take effect, we need to declare and authorize it in Androidmanifest.xml as follows:
<provider android:name= ". Personprovider "
android:authorities=" Com.scott.provider.PersonProvider "
Where android:multiprocess represents whether to allow multiple process operations. In addition, we can declare the appropriate permissions for it, the corresponding property is: Android:permission.
2. Call the Personprovider class:
After completing the person's contentprovider, let's take a look at how to access it. This step we completed in the mainactivity, look at the following code:
Package com.scott.provider;
Import java.util.ArrayList;
Import android.app.Activity;
Import Android.content.ContentResolver;
Import Android.content.ContentUris;
Import android.content.ContentValues;
Import Android.database.Cursor;
Import Android.database.CursorWrapper;
Import Android.net.Uri;
Import Android.os.Bundle;
Import Android.os.Handler;
Import Android.os.Message;
Import Android.view.View;
Import Android.widget.ListView;
Import Android.widget.SimpleCursorAdapter;
public class Mainactivity extends activity {private Contentresolver resolver;
Private ListView ListView;
Private static final String authority = "Com.scott.provider.PersonProvider";
private static final Uri Person_all_uri = Uri.parse ("content://" + Authority + "/persons");
Private Handler Handler = new Handler () {public void Handlemessage (msg) {//update records.
Requery ();
};
}; @Override public void OnCreate (Bundle savediNstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.main);
Resolver = Getcontentresolver ();
ListView = (ListView) Findviewbyid (R.id.listview); Notify Getcontentresolver (). Registercontentobserver (Person_all_uri, True, New Personobserver () for Person_all_uri registration changes (
handler)); /** * Initialize * @param view/public void init (view view) {arraylist<person> persons = NE
W arraylist<person> ();
Person Person1 = new Person ("Ella", "lively Girl");
Person Person2 = new Person ("Jenny", "Beautiful Girl");
Person Person3 = new Person ("Jessica", "Sexy Girl");
Person person4 = new Person ("Kelly", "A Hot Baby");
Person person5 = new Person ("Jane", "Pretty Woman");
Persons.add (Person1);
Persons.add (Person2);
Persons.add (Person3);
Persons.add (PERSON4);
Persons.add (PERSON5); for (person person:persons) {contentvalues Values = new Contentvalues ();
Values.put ("name", Person.name);
Values.put ("Age", person.age);
Values.put ("info", person.info);
Resolver.insert (Person_all_uri, values); /** * Query All records * @param view */public void query (view view) {//Uri Persononeuri = Content
Uris.withappendedid (Person_all_uri, 1), query _id 1 records Cursor C = resolver.query (Person_all_uri, NULL, NULL, NULL, NULL); Cursorwrapper cursorwrapper = new Cursorwrapper (c) {@Override public String getString (in T columnindex) {//will be preceded by the Age if (getColumnName (columnindex). Equals ("info")) {int. = GetInt
(Getcolumnindex ("Age"));
Return age + "years old," + super.getstring (columnindex);
Return super.getstring (columnindex);
}
}; Cursor must contain the "_id" field simplecursoradapter adapter = new Simplecursoradapter (this, Android. R.layout.simple_list_item_2, CursOrwrapper, new string[]{"name", "info"}, new int[]{android. R.id.text1, Android.
R.ID.TEXT2});
Listview.setadapter (adapter); Startmanagingcursor (Cursorwrapper); Manage cursor}/** * Insert a record * @param view */public void Insert (view view) {Person person = n
EW person ("Alina", "attractive");
Contentvalues values = new Contentvalues ();
Values.put ("name", Person.name);
Values.put ("Age", person.age);
Values.put ("info", person.info);
Resolver.insert (Person_all_uri, values);
/** * Update a record * @param view */public void update (view view) {Person of person = new person ();
Person.name = "Jane";
Person.age = 30;
Updates the Record age field for the specified name to contentvalues values = new Contentvalues ();
Values.put ("Age", person.age);
Resolver.update (Person_all_uri, values, "name =?", new String[]{person.name}); Update the age of _id 1 to the//Uri Updateuri = Contenturis.withappendedid (PERSOn_all_uri, 1);
Resolver.update (Updateuri, values, NULL, NULL); /** * Delete a record * @param view */public void Delete (view view) {///delete _id 1 of the record Uri Deluri =
Contenturis.withappendedid (Person_all_uri, 1);
Resolver.delete (Deluri, NULL, NULL);
Delete all records//Resolver.delete (Person_all_uri, NULL, NULL);
/** * Re-query */private void Requery () {//The actual operation can query the aggregate information after adapter.notifydatasetchanged ();
query (NULL);
}
}
We see that in the above code, it is relatively simple to test each case separately. We mainly talk about the registercontentobserver.
In the previous Personprovider we also mentioned that when data is changed, a notification is sent to the specified URI visitor to facilitate the update of the query record. We note that it is not enough to contentprovider, we also need to register a contentobserver in the visitor to receive this notice. Below we create a
Personobserver:
package com.scott.provider;
Import Android.database.ContentObserver;
Import Android.os.Handler;
Import Android.os.Message;
Import Android.util.Log;
public class Personobserver extends Contentobserver {public
static final String TAG = "Personobserver";
Private Handler Handler;
Public Personobserver (Handler Handler) {
super (Handler);
This.handler = handler;
}
@Override public
void OnChange (Boolean selfchange) {
super.onchange (selfchange);
LOG.I (TAG, "data changed, try to requery.");
Send a message to the handler, update the query record
msg = new messages ();
Handler.sendmessage (msg);
}
As a result, when ContentProvider is notified, we can receive it immediately, sending a message to handler to requery the record so that we can see the latest record information.
Finally, we'll add a MIME type filter to the mainactivity in Androidmanifest.xml, telling the system what type of information mainactivity can handle:
<!--MIME type-->
<intent-filter>
<data android:mimetype= "vnd.android.cursor.dir/ Vnd.scott.person "/>
</intent-filter>
<intent-filter>
<data android:mimetype=" Vnd.android.cursor.item/vnd.scott.person "/>
This completes the visitor's code, and we look at the effect:
Since there are too many types of operation, I will not show it here, we can try it by ourselves.
Original link: http://blog.csdn.net/liuhe688/article/details/7050868
The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.