Usage of ContentProvider in Android Development

Source: Internet
Author: User

Preface

Content Provider provides a unified interface for data storage and data retrieval. It can share data in different applications, in the previous article about how to use SQLite developed by Android, SQLite can only share data in the same program. In addition, android provides Content providers for some common data, such as audio, video, images, and address book, so that we can conveniently operate on these types of data. The advantage of using ContentProvider is that developers do not need to consider how data is stored internally. For example, if we want to use ContenProvider to store data, you only need to tell the insert function the uri of the ContentProvider and the data you want to store (including the column name and value). The query is the same. You only need to enter the Uri and the query Table, column name, and query conditions, we do not need to know how to perform these operations in ContentProvider.

  Lab Basics

To understand the content of this experiment, you need to use the following classes related to ContentProvider.

  UriMatcher:

To understand UriMatcher, you must first understand the Uri Representation Method in android. As we all know, Uri is a common resource identifier, which represents the data to be operated, and each resource in Android (such as text, images, videos, etc.) can all be represented by Uris. The Uri in Android consists of the following three parts: "content: //" (authory), data path, and resource ID (optional, indicates a specific resource. If no ID exists, it indicates the whole resource under the path. Therefore, the three parameters of the addUri () function correspond to the preceding three parameters.

The matching process of UriMatcher is divided into three steps: Initialize UriMatcher; register the Uri to be used; match with the registered Uri.

  ContentResolver:

When ContentProvider is used to share data in different applications, the data exposure method is similar to that of tables in the database. ContentResolver uses database-like methods to access data from ContentProvider. It queries the data provided in ContentProvider through Uri, you also need to know the name of the target database, the Data Type of the data segment, or the resource ID.

  SQLiteQueryBuilder:

SQLiteQueryBuilder is an auxiliary class used to produce SQL query statements, allowing you to conveniently access SQLiteDatabase. when constructing an SQL query statement, you also need to specify the table name, column name, and where condition.

  Experiment Process

This article uses an example to implement a ContentProvider. In fact, we generally do not need to implement it ourselves, but use the built-in ContentProvider of andorid, I have a deeper understanding of its principles and will be able to use the built-in functions in the future. This is what Mr. mars said. I have not had enough fire to understand it yet. The steps for implementing ContentProvider are summarized as follows:

  

Four java files are required in the program. The following describes the precautions for implementing these classes:

  FirstProviderMetaData class:

Because many constants are used in the subclass obtained by the inheritance class FirstContentProvider, we have created a class dedicated to store these constants. Here the class is named FirstProviderMetaData with the authorty name, database Name, database version number, table name, word table name, sub-Table Uri, sub-Table ContentProvider data type, and so on. The Word Table inherits the BaseColumns class, And the BaseColumns class already contains the _ ID and _ COUNT columns.

  DatabaseHelper class:

Similar to using SQLite in android, here we also need a subclass that inherits SQLiteOpenHelper. The subclass name is DatabaseHelper. We have created a table in the callback function onCreate () of the subclass, both the table name and the column name reference the constants defined in the FirstProviderMetaData class.

  FirstContentProvider class:

Create a new class named FirstContentProvider that inherits the class ContentProvider and must override the following five methods of the parent class. Otherwise, an error is returned. The five methods are onCreate (), getType (), insert (), update (), and delete ().

OnCreate () is the callback function, which is called when ContentProvider is created. This program creates an SQLite database using DatabaseHelper in this function.

The getType () method returns the Data Type represented by this Uri based on the input Uri. In the function, UriMatcher is used to match the parameters passed in by the function to obtain its data type.

The insert () function inserts a specified value into a specified database table. After the insert operation is complete, a new record is generated, then, use the record and the table Uri to generate a new Uri. This Uri indicates the Uri of the inserted record. This Uri is returned by the function.

  MainActivity class:

In MainActivity, there are mainly two buttons, which are bound with listeners to complete insertion and query operations.

When the insert button is clicked, A ContentResolver is first obtained in the listener function, and then the ContentProvider's insert method is automatically called when the ContentResolver's insert method is executed, because the first parameter in the insert method of ContentResolver is the Uri of a ContentProvider.

  AndroidManifest. xml:

To use ContentProvider, you must register it in AndroidManifest. xml and add the following declaration to the activity Tag:

<provider android:name="com.example.cptest.FirstContentProvider" android:authorities="com.example.cptest.FirstContentProvider" />

  Code and comments of the experiment:

MainActivity. java:

Copy codeThe Code is as follows: package com. example. cptest;

// Import com. example. cptest. FirstProviderMetaData;
Import com. example. cptest. FirstProviderMetaData. UserTableMetaData;

Import android. app. Activity;
Import android. content. ContentValues;
Import android. database. Cursor;
Import android.net. Uri;
Import android. OS. Bundle;
Import android. view. Menu;
Import android. view. View;
Import android. view. View. OnClickListener;
Import android. widget. Button;

Public class MainActivity extends Activity {

Private Button insert = null;
Private Button query = null;
@ Override
Public void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
SetContentView (R. layout. activity_main );
Insert = (Button) findViewById (R. id. insert );
Insert. setOnClickListener (new InsertOnClickListener ());
Query = (Button) findViewById (R. id. query );
Query. setOnClickListener (new QueryOnClickListener ());
System. out. println (getContentResolver (). getType (FirstProviderMetaData. UserTableMetaData. CONTENT_URI ));
}

// Insert a record into the subtable
Public class InsertOnClickListener implements OnClickListener {

Public void onClick (View arg0 ){
// TODO Auto-generated method stub
ContentValues values = new ContentValues ();
Values. put (FirstProviderMetaData. UserTableMetaData. USER_NAME, "tornadomeet ");
// The insert method of ContentResolver is actually used.
// There are two parameters in the insert statement. The first parameter represents the Uri of ContentProvider, and the second parameter is the value to be inserted. Insert Function
// If this parameter is set to 1, the insert method of ContentProvider is automatically called.
Uri uri = getContentResolver (). insert (FirstProviderMetaData. UserTableMetaData. CONTENT_URI,
Values );
System. out. println ("uri --->" + uri. toString ());
}
}

// The query method in ContentResolver is also used for queries.
Public class QueryOnClickListener implements OnClickListener {
Public void onClick (View v ){
// TODO Auto-generated method stub
Cursor c = getContentResolver (). query (FirstProviderMetaData. UserTableMetaData. CONTENT_URI,
Null, null );
While (c. moveToNext ())
System. out. println (c. getString (c. getColumnIndex (UserTableMetaData. USER_NAME )));
}
}

@ Override
Public boolean onCreateOptionsMenu (Menu menu ){
GetMenuInflater (). inflate (R. menu. activity_main, menu );
Return true;
}
}

DatabaseHelper:Copy codeThe Code is as follows: package com. example. cptest;

Import android. content. Context;
Import android. database. sqlite. SQLiteDatabase;
Import android. database. sqlite. SQLiteOpenHelper;
Import android. database. sqlite. SQLiteDatabase. CursorFactory;

Public class DatabaseHelper extends SQLiteOpenHelper {

Private static final int VERSON = 1; // default database version

// The class that inherits the SQLiteOpenHelper class must have its own Constructor
// This constructor has four parameters and calls the constructor of the parent class directly. The first parameter is the class itself, and the second parameter is the database name;
// The third parameter is used to set the cursor object. Here it is generally set to null. Parameter 4 is the database version number.
Public DatabaseHelper (Context context, String name, CursorFactory factory, int verson ){
Super (context, name, factory, verson );
}

// The constructor has three parameters because it sets the 3rd parameters of the preceding function to null.
Public DatabaseHelper (Context context, String name, int verson ){
This (context, name, null, verson );
}

// The constructor has only two parameters. The base hill of the above function fixes the version number.
Public DatabaseHelper (Context context, String name ){
This (context, name, VERSON );
}

// This function is called when the database is first created
@ Override
Public void onCreate (SQLiteDatabase arg0 ){
// TODO Auto-generated method stub
System. out. println ("create a database ");
// ExecSQL () is the SQL statement in the execution parameter. Therefore, the statements in the parameter must comply with the SQL syntax. Here we create a table.
// Arg0.execSQL ("create table user1 (id int, name varchar (20)"); the following statement format is similar to this statement
// Arg0.execSQL ("create table" + FirstProviderMetaData. USERS_TABLE_NAME
// + "(" + FirstProviderMetaData. UserTableMetaData. _ ID
// + "Integer primary key autoincrement," + // The ID type is an auto-increment INTEGER.
// FirstProviderMetaData. UserTableMetaData. USER_NAME + "varchar (20 ));"
//);
// Arg0.execSQL ("create table user1 (id int, name varchar (20 ))");
Arg0.execSQL ("create table" + FirstProviderMetaData. USERS_TABLE_NAME + "("
+ FirstProviderMetaData. UserTableMetaData. _ ID + "integer primary key autoincrement ,"
+ FirstProviderMetaData. UserTableMetaData. USER_NAME + "varchar (20 ))");
System. out. println ("create a database OK ");
}

@ Override
Public void onUpgrade (SQLiteDatabase arg0, int arg1, int arg2 ){
// TODO Auto-generated method stub
System. out. println ("update a database ");
}

}

FirstProviderMetaData. java:Copy codeThe Code is as follows: package com. example. cptest;

Import android.net. Uri;
Import android. provider. BaseColumns;

Public class FirstProviderMetaData {

// Here the AUTHORTY is the full name of the package + the full name of the ContentProvider subclass
Public static final String AUTHORTY = "com. example. cptest. FirstContentProvider ";
// Database Name
Public static final String DATABASE_NAME = "FisrtProvider. db ";
// Database version number
Public static final int DATABASE_VERSION = 1;
// Name of the table in the database
Public static final String USERS_TABLE_NAME = "users ";
// Word table in the table
Public static final class UserTableMetaData implements BaseColumns {
// Subtable name
Public static final String TABLE_NAME = "users ";
// CONTENT_URI is a constant Uri; parse converts text to Uri
Public static final Uri CONTENT_URI = Uri. parse ("content: //" + AUTHORTY + "/users ");
// Return the Data Type of the table in ContentProvider
Public static final String CONTENT_TYPE = "vnd. android. cursor. dir/vnd. firstprovider. user ";
// Return the item data type in the ContentProvider table
Public static final String CONTENT_TYPE_ITEM = "vnd. android. cursor. item/vnd. firstprovider. user ";
// Subtable column name
Public static final String USER_NAME = "name ";
// The default Sorting Algorithm for records in the Table. Here is the descending order.
Public static final String DEFAULT_SORT_ORDER = "_ id desc ";

}

}

FirstContentProvider. java:Copy codeThe Code is as follows: package com. example. cptest;

Import java. util. HashMap;

Import android. content. ContentProvider;
Import android. content. ContentUris;
Import android. content. ContentValues;
Import android. content. UriMatcher;
Import android. database. Cursor;
Import android. database. SQLException;
Import android. database. sqlite. SQLiteDatabase;
Import android. database. sqlite. SQLiteQueryBuilder;
Import android.net. Uri;
Import android. text. TextUtils;

Import com. example. cptest. FirstProviderMetaData. UserTableMetaData;

Public class FirstContentProvider extends ContentProvider {

// Define a UriMatcher class object to match the Uri.
Public static final UriMatcher uriMatcher;
// Group ID
Public static final int INCOMING_USER_COLLECTION = 1;
// ID of a single time
Public static final int INCOMING_USER_SIGNAL = 2;
Private DatabaseHelper dh; // defines a DatabaseHelper object
Static {
UriMatcher = new UriMatcher (UriMatcher. NO_MATCH); // UriMatcher. NO_MATCH indicates that the return code does not match any path.
UriMatcher. addURI (FirstProviderMetaData. AUTHORTY, "users", INCOMING_USER_COLLECTION );
UriMatcher. addURI (FirstProviderMetaData. AUTHORTY, "users/#", INCOMING_USER_SIGNAL); // # indicates a single
}

Public static HashMap <String, String> userProjectionMap; // creates a new HashMap, which is useful for subsequent insert operations.
Static
{
UserProjectionMap = new HashMap <String, String> ();
// You can directly call the public variable of another class. The two parameters in put are the same,
// This is because an alias is used for the columns in the database table, so the same name is used.
UserProjectionMap. put (UserTableMetaData. _ ID, UserTableMetaData. _ ID );
UserProjectionMap. put (UserTableMetaData. USER_NAME, UserTableMetaData. USER_NAME );
}

// Obtain the ContentProvider data type. The returned parameter Uri represents the data type.
@ Override
Public String getType (Uri arg0 ){
// TODO Auto-generated method stub
System. out. println ("getType ");
Switch (uriMatcher. match (arg0 )){
// When the first two items (Protocol + path) of the Uri are met by matcher, the value of the switch statement is 1st items of the Uri, Which is INCOMING_USER_COLLECTION.
Case INCOMING_USER_COLLECTION:
Return UserTableMetaData. CONTENT_TYPE;
Case INCOMING_USER_SIGNAL: // same as above
Return UserTableMetaData. CONTENT_TYPE_ITEM;
Default:
Throw new IllegalArgumentException ("Unknown URI" + arg0); // throw is used to handle exceptions. java syntax
}
}

@ Override
Public int delete (Uri uri, String selection, String [] selectionArgs ){
// TODO Auto-generated method stub
System. out. println ("delete ");
Return 0;
}

@ Override
Public int update (Uri uri, ContentValues values, String selection,
String [] selectionArgs ){
// TODO Auto-generated method stub
System. out. println ("update ");
Return 0;
}

@ Override
Public Uri insert (Uri uri, ContentValues values ){
// TODO Auto-generated method stub
System. out. println ("insert ");
// Dh = new DatabaseHelper (getContext (), FirstProviderMetaData. DATABASE_NAME );
SQLiteDatabase db = dh. getWritableDatabase ();
Long rowId = db. insert (UserTableMetaData. TABLE_NAME, null, values );
// System. out. println ("insert OK ");
// System. out. println ("" + rowId );
If (rowId> 0 ){
// Send a notification to the listener indicating that the data has changed
// ContentUris is a tool class
Uri insertedUserUri = ContentUris. withAppendedId (UserTableMetaData. CONTENT_URI, rowId );
GetContext (). getContentResolver (). policychange (insertedUserUri, null );

Return insertedUserUri;
}
Throw new SQLException ("Failed to insert row into" + uri );
}

// Callback function, called when ContentProvider is created
@ Override
Public boolean onCreate (){
// TODO Auto-generated method stub
System. out. println ("onCreate ");
Dh = new DatabaseHelper (getContext (), FirstProviderMetaData. DATABASE_NAME); // create one DatabaseHelper object
Return true;
}

@ Override
Public Cursor query (Uri uri, String [] projection, String selection,
String [] selectionArgs, String sortOrder ){
// TODO Auto-generated method stub
System. out. println ("query ");
SQLiteQueryBuilder qb = new SQLiteQueryBuilder ();
Switch (uriMatcher. match (uri )){
Case INCOMING_USER_COLLECTION:
Qb. setTables (UserTableMetaData. TABLE_NAME); // you can specify the table name.
Qb. setProjectionMap (userProjectionMap); // userProjectionMap indicates the hashmap created above.
Break;
Case INCOMING_USER_SIGNAL:
Qb. setTables (UserTableMetaData. TABLE_NAME); // you can specify the table name.
Qb. setProjectionMap (userProjectionMap); // userProjectionMap indicates the hashmap created above.
// Uri. getPathSegments () Get the Path part, that is, remove the uri protocol + authory part, and get the rest part in segments.
// Part
Qb. appendWhere (UserTableMetaData. _ ID + "=" + uri. getPathSegments (). get (1); // set the where Condition
Break;
}
// Sort
String orderBy;
If (TextUtils. isEmpty (sortOrder )){
OrderBy = UserTableMetaData. DEFAULT_SORT_ORDER; // use the default sorting when the input sorting parameter is null.
}
Else {
OrderBy = sortOrder; // use the specified sorting method when the value is not empty.
}
SQLiteDatabase db = dh. getWritableDatabase ();
// Query with input parameters
Cursor c = qb. query (db, projection, selection, selectionArgs, null, null, sortOrder );
// Send a notification
C. setNotificationUri (getContext (). getContentResolver (), uri );
Return c;
}

}

Related Article

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.