Android: Implementing cross-Program data sharing

Source: Internet
Author: User

For simplicity, we continue to develop on the basis of the Databasetest project in the previous chapter by adding an external access interface to it through a content provider.

Open the Databasetest project, first use the Toast pop-up in Mydatabasehelper to create the database successful prompt to remove, because cross-program Access we do not directly use toast. Then add a Databaseprovider class with the code as follows:

Public class Databaseprovider extends ContentProvider {

public static final int book_dir = 0;

public static final int book_item = 1;

public static final int category_dir = 2;

public static final int category_item = 3;

public static final String authority = "Com.example.databasetest.provider";

private static Urimatcher Urimatcher;

Private Mydatabasehelper DBHelper;

static {

Urimatcher = new Urimatcher (urimatcher.no_match);

Urimatcher.adduri (Authority, "book", Book_dir);

Urimatcher.adduri (Authority, "book/#", Book_item);

Urimatcher.adduri (Authority, "category", Category_dir);

Urimatcher.adduri (Authority, "category/#", Category_item);

}

@Override

public Boolean onCreate () {

DBHelper = new Mydatabasehelper (GetContext (), "bookstore.db", NULL, 2);

return true;

}

@Override

Public Cursor query (Uriuri, string[] projection, String selection, string[] Selectionargs, Stringsortorder) {

// query data

Sqlitedatabase db =dbhelper.getreadabledatabase ();

cursor cursor = NULL;

Switch (Urimatcher.match (URI)) {

Case BOOK_DIR:

cursor = db.query ("book", Projection, selection, selectionargs,null, NULL, sortOrder);

Break

Case Book_item:

String bookId = uri.getpathsegments (). get (1);

cursor = db.query ("book", projection, "id =?", new string[]{bookId}, NULL, Null,sortorder);

Break

Case CATEGORY_DIR:

Cursor =db.query ("Category", projection, selection, Selectionargs, NULL, null,sortorder);

Break

Case Category_item:

String categoryId = uri.getpathsegments (). get (1);

cursor = db.query ("Category", projection, "id =?", new string[]{categoryId}, NULL, NULL, sortOrder);

Break

Default

Break

}

return cursor;

}

@Override

Public URI insert (URI uri, contentvalues values) {

// Add data

Sqlitedatabase db =dbhelper.getwritabledatabase (); Uri Urireturn = null;

Switch (Urimatcher.match (URI)) {

Case BOOK_DIR:

Case Book_item:

Long Newbookid = Db.insert ("book", null, values);

Urireturn = Uri.parse ("content://" + Authority + "/book/" +newbookid);

Break

Case CATEGORY_DIR:

Case Category_item:

Long Newcategoryid = Db.insert ("Category", null,values);

Urireturn = Uri.parse ("content://" + Authority + "/category/" +Newcategoryid);

Break

Default

Break

}

return urireturn;

}

@Override

public int update (Uri uri,contentvalues values, String selection, string[] Selectionargs) {

// Update data

Sqlitedatabase db = Dbhelper.getwritabledatabase ();

int updatedrows = 0;

Switch (Urimatcher.match (URI)) {

Case BOOK_DIR:

Updatedrows = Db.update ("book", Values, selection, Selectionargs);

Break

Case Book_item:

String bookId = uri.getpathsegments (). get (1);

updatedrows = db.update ("book", values, "id =?", new string[]{bookId});

Break

Case CATEGORY_DIR:

Updatedrows =db.update ("Category", values, selection, Selectionargs);

Break

Case Category_item:

String categoryId = uri.getpathsegments (). get (1);

up da T Ed R ow s = db.update ("Category", values, "id =?", new string[]{categoryId});

Break

Default

Break

}

return updatedrows;

}

@Override

public int Delete (URI Uri, String selection, string[] Selectionargs) {

// Delete data

Sqlitedatabase db = Dbhelper.getwritabledatabase ();

int deletedrows = 0;

Switch (Urimatcher.match (URI)) {

Case BOOK_DIR:

Deletedrows = Db.delete ("book", Selection,selectionargs);

Break

Case Book_item:

String bookId = uri.getpathsegments (). get (1);

Deletedrows = Db.delete ("book", "id =?", new string[] {bookId});

Break

Case CATEGORY_DIR:

Deletedrows = Db.delete ("Category", Selection, Selectionargs);

Break

Case Category_item:

String categoryId = uri.getpathsegments (). get (1);

deletedrows = Db.delete ("Category", "id =?", new string[]{categoryId});

Break

Default

Break

}

return deletedrows;

}

@Override

Public String GetType (Uriuri) {

Switch (Urimatcher.match (URI)) {

Case BOOK_DIR:

Return "Vnd.android.cursor.dir/vnd.com.example.databasetest. Provider.book ";

Case Book_item:

return "Vnd.android.cursor.item/vnd.com.example.databasetest.provider.book";

Case CATEGORY_DIR:

return "Vnd.android.cursor.dir/vnd.com.example.databasetest.provider.category";

Case Category_item:

return "Vnd.android.cursor.item/vnd.com.example.databasetest.provider.category";

}

return null;

}

}

The code is long, but don't worry, it's easy to understand, because all that is used is the knowledge we learned in the previous section. First, at the beginning of the class, four constants are defined, respectively, for accessing all the data in the Book table, accessing a single piece of data in the Book table, accessing all the data in the category table, and accessing a single piece of data in the category table. The Urimatcher is then initialized in a static code block, adding several URI formats that are expected to match.

Next is the concrete implementation of each abstract method, first look at the OnCreate () method, the code of this method is very short, is to create an instance of Mydatabasehelper, and then return true to indicate that the content provider initialization succeeded, At this point the database has completed the Create or upgrade operation.

Then take a look at the query () method, in this method first get the instance of Sqlitedatabase, and then according to the URI parameter passed to determine which table the user wants to access, and then call Sqlitedatabase query () queries, and the Cursor object returned It's good to go back. Note that when accessing a single piece of data there is a detail, called the Getpathsegments () method of the URI object, which splits the section after the content URI permission with the "/" symbol and puts the segmented result into a list of strings, the No. 0 Location is the path, the 1th location is the ID. After the ID is obtained, the function of querying single data is realized by selection and Selectionargs parameter constraints.

The next is the Insert () method, it is also the first to obtain the Sqlitedatabase instance, and then according to the Uri parameter passed to determine which table the user wants to add data, and then call the Sqlitedatabase Insert () method to add it. Note that the Insert () method requires that you return a URI that represents this new data, so we also need to call the Uri.parse () method to parse a content URI into a URI object, which, of course, ends with the ID of the new data.

Next is the update () method, and I believe the code in this method is completely difficult for you. It is also the first to obtain an instance of Sqlitedatabase, and then according to the Uri parameter passed in to determine which table the user wants to update the data, and then call the Sqlitedatabase Update () method to update it, the number of affected rows will be returned as the return value.

The following is the Delete () method, is it easier to feel the more in the back? Because you're getting better, really getting the hang of it. This is still the first to obtain an instance of Sqlitedatabase, and then according to the Uri parameter passed to determine which table the user wants to delete data, and then call the Sqlitedatabase Delete () method to delete It is good, the number of deleted rows will be returned as the return value.

Finally, the GetType () method, the code in this method is written exactly according to the formatting rules described in the previous section, I believe there is no need to explain.

That way we've written all the code in the content provider, but it's a small step away from implementing a cross-program data share, because you also need to register the content provider in the Androidmanifest.xml file as follows:

<manifestxmlns:android= "Http://schemas.android.com/apk/res/android" package= "Com.example.databasetest"

Android:versioncode= "1" android:versionname= "1.0" >

......

<applicationandroid:allowbackup= "true" android:icon= "@drawable/ic_launcher" android:label= "@string/app_name" Android:theme= "@style/apptheme" >

......

<providerandroid:name= "Com.example.databasetest.DatabaseProvider" android:authorities= " Com.example.databasetest.provider ">

</provider>

</application>

</manifest>

As you can see, here we use the <provider> tag to register the Databaseprovider content provider, specify the full name of the class in the Android:name attribute, and Android:authorities property specifies the permissions for the content provider.

Now Databasetest this project has the ability to share data across programs, let's try it quickly. First, you need to remove the Databasetest program from the emulator to prevent the legacy data from the previous chapter

Cause interference. Then run the project and reinstall the DATABASETEST program on the emulator. Then close off the Databasetest project and create a new project Providertest, and we'll go through this program to access the data in Databasetest.

Let's write the layout file first, modify the code in the Activity_main.xml as follows:

<linearlayoutxmlns:android= "Http://schemas.android.com/apk/res/android" android:layout_width= "match_parent" android:layout_height= "Match_parent "

android:orientation= "Vertical" >

<buttonandroid:id= "@+id/add_data" android:layout_width= "match_parent" android:layout_height= "Wrap_content" android:text= "Add Tobook"/>

<button android:id= "@+id/query_data" android:layout_width= "match_parent" android:layout_height= "Wrap_content" android:text= "Query Frombook"/>

<buttonandroid:id= "@+id/update_data" android:layout_width= "match_parent" android:layout_height= "Wrap_content" android:text= "Updatebook"/>

<buttonandroid:id= "@+id/delete_data" android:layout_width= "match_parent" android:layout_height= "Wrap_content" android:text= "Delete Frombook"/>

</LinearLayout>

The layout file is simple, with four buttons placed to add, query, modify, and delete data, respectively. Then modify the code in the mainactivity as follows:

public class Mainactivity Extendsactivity {

Private String newId;

@Override

Protectedvoid onCreate (Bundle savedinstancestate) {

Super.oncreate (savedinstancestate);

Setcontentview (R.layout.activity_main);

Button AddData = (button) Findviewbyid (R.id.add_data);

Adddata.setonclicklistener (New Onclicklistener () {

@Override

public void OnClick (View v) {

// Add data

URI Uri =uri.parse ("Content://com.example.databasetest. Provider/book ");

Contentvalues values = Newcontentvalues ();

Values.put ("name", "A Clash of Kings");

Values.put ("Author", "George Martin");

Values.put ("pages", 1040);

Values.put ("Price", 22.85);

Uri Newuri = Getcontentresolver (). Insert (URI, values);

NewId = Newuri.getpathsegments (). get (1);

}

});

Button Querydata = (button) Findviewbyid (R.id.query_data);

Querydata.setonclicklistener (New Onclicklistener () {

@Override

public void OnClick (View v) {

// query data

URI Uri =uri.parse ("Content://com.example.databasetest. Provider/book ");

cursor cursor = getcontentresolver (). Query (URI, null,null,null, NULL);

if (cursor! = NULL) {

while (Cursor.movetonext ()) {

String name = cursor.getstring (cursor. getcolumnindex ("name"));

String author =cursor.getstring (cursor. Getcolumnindex ("author"));

int pages = Cursor.getint (cursor.getcolumnindex("pages"));

Double price =cursor.getdouble (cursor getcolumnindex ("price"));

LOG.D ("Mainactivity", "book name is" + name);

LOG.D ("Mainactivity", "book author is" + author);

LOG.D ("Mainactivity", "book pages are" + pages);

LOG.D ("Mainactivity", "book Price are" + price);

}

}

}

Cursor.close ();

}

Button UpdateData = (button) Findviewbyid (R.id.update_data);

Updatedata.setonclicklistener (New Onclicklistener () {

@Override

public void OnClick (View v) {

// Update data

URI Uri =uri.parse ("Content://com.example.databasetest. provider/book/"+newid);

Contentvalues values = new Contentvalues ();

Values.put ("name", "A Storm of Swords");

Values.put ("pages", 1216);

Values.put ("Price", 24.05);

Getcontentresolver (). Update (URI, values, NULL, NULL);

}

});

Button DeleteData = (button) Findviewbyid (R.id.delete_data);

Deletedata.setonclicklistener (New Onclicklistener () {

@Override

public void OnClick (View v) {

// Delete data

URI Uri =uri.parse ("Content://com.example.databasetest. provider/book/"+newid);

Getcontentresolver (). Delete (uri,null, null);

}

});

}

}

As you can see, we dealt with the logic of adding and removing changes in the Click events of the four buttons respectively. When adding data, first calls the Uri.parse () method to parse a content URI into a URI object, then stores the data to be added to the Contentvalues object, and then calls the Contentresolver Insert () method to perform the add operation. Note that the Insert () method returns a Uri object that contains the ID of the new data, and we take the ID out of the Getpathsegments () method and use it later.

When querying data, it is also called the Uri.parse () method to parse a content URI into a URI object, and then call the Contentresolver query () method for querying the data, and the result of the query is of course stored in the Cursor object. The Cursor is then traversed, and the query results are extracted and printed out.

When updating data, the content URI is parsed into a URI object, then the data that you want to update is stored in the Contentvalues object, and then the update () method of Contentresolver is called. Note here that in order not to let other rows in the Book table be affected, when the Uri.parse () method is called, an ID is added to the end of the content Uri, which is the one returned when the data is added. This means that we only want to update the data that we just added, and the other rows in the Book table will not be affected.

When deleting data, the same method is used to parse a content URI ending with an ID, and then call Contentresolver's Delete () method to perform the delete operation. Since we specify an ID in the content URI, only the row with the corresponding ID will be deleted, and the rest of the data in the Book table will not be affected.

Now run the Providertest project and the interface shown in 7.4 will be displayed.

Figure 7.4

Click on the Add to book button, the data should have been added to the Databasetest program database, we can click the Query from the book button to check, print log 7.5 is shown.

Figure 7.5

Then click the Update Book button to update the data, and then click the Query from the book button to check, as shown in result 7.6.

Figure 7.6

Finally, click the Delete from book button to delete the data, and then click the query from the book button to query the data.

As you can see, our cross-program shared data function has been successfully implemented! Now not only the Providertest program, any program can easily access the data in Databasetest, and we do not have to worry about privacy data leakage.

Android: Implementing cross-Program data sharing

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.