ContentProvider,從字面意義上理解,內容提供者,這個類目的就是一個橋梁的作用,讓一個應用的數據(SQLiteDatabase, SharedPreferences,Xml,Txt等數據),通過ContentProvider可以讓其他的應用訪問。
理論知識
(一)、ContentProvider簡介
當應用繼承ContentProvider類,並重寫該類用於提供數據和存儲數據的方法,就可以向其他應用共享其數據。雖然使用其他方法也可以對外共享數據,但數據訪問方式會因數據存儲的方式而不同,如:采用文件方式對外共享數據,需要進行文件操作讀寫數據;采用sharedpreferences共享數據,需要使用sharedpreferences API讀寫數據。而使用ContentProvider共享數據的好處是統一了數據訪問方式。
(二)、Uri類簡介
Uri代表了要操作的數據,Uri主要包含了兩部分信息:1.需要操作的ContentProvider ,2.對ContentProvider中的什麼數據進行操作,一個Uri由以下幾部分組成:
1.scheme:ContentProvider(內容提供者)的scheme已經由Android所規定為:content://。
2.主機名(或Authority):用於唯一標識這個ContentProvider,外部調用者可以根據這個標識來找到它。
3.路徑(path):可以用來表示我們要操作的數據,路徑的構建應根據業務而定,如下:
a、要操作contact表中id為10的記錄,可以構建這樣的路徑:/contact/10
b、要操作contact表中id為10的記錄的name字段, contact/10/name
c、要操作contact表中的所有記錄,可以構建這樣的路徑:/contact
要操作的數據不一定來自數據庫,也可以是文件等他存儲方式,如下:
要操作xml文件中contact節點下的name節點,可以構建這樣的路徑:/contact/name
如果要把一個字符串轉換成Uri,可以使用Uri類中的parse()方法,如下:
Uri uri = Uri.parse(content://com.figo.helloworld.MyContentProvider/contacter )
(三)、UriMatcher、ContentUris和ContentResolver簡介
因為Uri代表了要操作的數據,所以我們很經常需要解析Uri,並從Uri中獲取數據。Android系統提供了兩個用於操作Uri的工具類,分別為UriMatcher 和ContentUris 。掌握它們的使用,會便於我們的開發工作。
UriMatcher:用於匹配Uri,它的用法如下:
1.首先把你需要匹配Uri路徑全部給注冊上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路徑的返回碼(-1)。
UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//如果match()方法匹配content://com.figo.helloworld.MyContentProvider/contacter 路徑,返回匹配碼為1
uriMatcher.addURI(“content://com.figo.helloworld.MyContentProvider/contacter”, “contacter”, 1);//添加需要匹配uri,如果匹配就會返回匹配碼
//如果match()方法匹配 content://com.figo.helloworld.MyContentProvider/contacter/230路徑,返回匹配碼為2
uriMatcher.addURI(“content://com.figo.helloworld.MyContentProvider”, “contacter /#”, 2);//#號為通配符
2.注冊完需要匹配的Uri後,就可以使用uriMatcher.match(uri)方法對輸入的Uri進行匹配,如果匹配就返回匹配碼,匹配碼是調用addURI()方法傳入的第三個參數,假設匹配content://com.figo.helloworld.MyContentProvider/contacter路徑,返回的匹配碼為1。
ContentUris:用於獲取Uri路徑後面的ID部分,它有兩個比較實用的方法:
a、withAppendedId(uri, id)用於為路徑加上ID部分
b、parseId(uri)方法用於從路徑中獲取ID部分
ContentResolver:當外部應用需要對ContentProvider中的數據進行添加、刪除、修改和查詢操作時,可以使用ContentResolver 類來完成,要獲取ContentResolver 對象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法,來操作數據。
(四)、ContentProvider需要在AndroidManifest.xml中的注冊
package=com.figo.helloworld android:versionCode=1 android:versionName=1.0>
android:authorities=com.figo.helloworld.MyContentProvider >
實踐操作
這個實例裡面,在helloworld應用裡面,我們創建一個名為聯系人contacter的sqlitedatabase數據庫,裡面有一張表聯系人contacter,包含字段聯系人contacterid編號,name姓名,age年齡3個字段。然後通過contentprovider實現對sqlitedatabase數據的增刪改查操作,同時使用gridview將數據展現出來,然後在另外一個應用裡面Sudoku裡面通過helloworld提供的contentprovider實現對helloworld應用contacter數據庫的操作,從而實現數據的共享。
Helloworld應用
第一步、新建頁面contentproviderview.xml,friendview.xml
contentproviderview.xml
xmlns:android=http://schemas.android.com/apk/res/android
android:orientation=vertical
android:layout_width=fill_parent
android:layout_height=fill_parent>
friendview.xml
xmlns:android=http://schemas.android.com/apk/res/android
android:orientation=vertical
android:layout_width=fill_parent
android:layout_height=fill_parent>
第二步、新建SQLiteOpenHelper MySQLiteOpenHelper.java
/**
*
*/
package com.figo.helloworld;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
/**
* @author zhuzhifei
*
*/
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
private static final String SQLITE_NAME = contacter;
private static final int version = 1;
public MySQLiteOpenHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
public MySQLiteOpenHelper(Context context) {
super(context, SQLITE_NAME, null, version);
}
/*
* (non-Javadoc)
*
* @see
* android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite
* .SQLiteDatabase)
*/
@Override
public void onCreate(SQLiteDatabase arg0) {
// 新建一張聯系人contacter表,包含主鍵、名字、年齡字段
arg0.execSQL(CREATE TABLE contacter (contacterid integer primary key autoincrement,name varchar(20),age INTEGER));
}
/*
* (non-Javadoc)
*
* @see
* android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite
* .SQLiteDatabase, int, int)
*/
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
arg0.execSQL(DROP TABLE IF EXISTS contacter);
onCreate(arg0);
}
}
第三步、新建ContentProvider MyContentProvider.java
/**
*
*/
package com.figo.helloworld;
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;
import android.text.TextUtils;
/**
* @author zhuzhifei
*
*/
public class MyContentProvider extends ContentProvider {
private MySQLiteOpenHelper mySQLiteOpenHelper;
private final static int CONTACTER = 1;
private final static int CONTACTERS = 2;
private final static String AUTHORITY = com.figo.helloworld.MyContentProvider;
private static final UriMatcher pMatcher = new UriMatcher(
UriMatcher.NO_MATCH);
static {
pMatcher.addURI(AUTHORITY, contacter, CONTACTERS);
pMatcher.addURI(AUTHORITY, contacter/#, CONTACTER);
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#delete(android.net.Uri,
* java.lang.String, java.lang.String[])
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
SQLiteDatabase db = mySQLiteOpenHelper.getWritableDatabase();
int count = 0;
switch (pMatcher.match(uri)) {
case CONTACTERS:
count = db.delete(contacter, selection, selectionArgs);
break;
case CONTACTER:
long sid = ContentUris.parseId(uri);
String where = TextUtils.isEmpty(selection) ? contacterid=?
: selection + and contacterid=?;
String[] params = new String[] { String.valueOf(sid) };
if (!TextUtils.isEmpty(selection) && selectionArgs != null) {
params = new String[selectionArgs.length + 1];
for (int i = 0; i < selectionArgs.length; i++) {
params[i] = selectionArgs[i];
}
params[selectionArgs.length] = String.valueOf(sid);
}
count = db.delete(contacter, where, params);
break;
default:
throw new IllegalArgumentException(Unknow Uri: + uri);
}
return count;
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#getType(android.net.Uri)
*/
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
switch (pMatcher.match(uri)) {
case CONTACTERS:
return vnd.android.cursor.dir/MyContentProvider.contacter;
case CONTACTER:
return vnd.android.cursor.item/MyContentProvider.contacter;
default:
throw new IllegalArgumentException(Unknow Uri: + uri);
}
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#insert(android.net.Uri,
* android.content.ContentValues)
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
// TODO Auto-generated method stub
SQLiteDatabase db = mySQLiteOpenHelper.getWritableDatabase();
long pid = 0;
switch (pMatcher.match(uri)) {
case CONTACTERS:
pid = db.insert(contacter, name, values);
return ContentUris.withAppendedId(uri, pid);
case CONTACTER:
pid = db.insert(contacter, name, values);
String path = uri.toString();
return Uri
.parse(path.substring(0, path.lastIndexOf('/') + 1) + pid);
default:
throw new IllegalArgumentException(Unknow Uri: + uri);
}
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#onCreate()
*/
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
mySQLiteOpenHelper = new MySQLiteOpenHelper(this.getContext());
return true;
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#query(android.net.Uri,
* java.lang.String[], java.lang.String, java.lang.String[],
* java.lang.String)
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
SQLiteDatabase db = mySQLiteOpenHelper.getWritableDatabase();
switch (pMatcher.match(uri)) {
case CONTACTERS:
return db.query(contacter, projection, selection, selectionArgs,
null, null, sortOrder);
case CONTACTER:
long pid = ContentUris.parseId(uri);
String where = TextUtils.isEmpty(selection) ? contacterid=?
: selection + and contacterid=?;
String[] params = new String[] { String.valueOf(pid) };
if (!TextUtils.isEmpty(selection) && selectionArgs != null) {
params = new String[selectionArgs.length + 1];
for (int i = 0; i < selectionArgs.length; i++) {
params[i] = selectionArgs[i];
}
}
return db.query(contacter, projection, where, params, null, null,
sortOrder);
default:
throw new IllegalArgumentException(Unknow Uri: + uri);
}
}
/*
* (non-Javadoc)
*
* @see android.content.ContentProvider#update(android.net.Uri,
* android.content.ContentValues, java.lang.String, java.lang.String[])
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
SQLiteDatabase db = mySQLiteOpenHelper.getWritableDatabase();
int count = 0;
switch (pMatcher.match(uri)) {
case CONTACTERS:
count = db.update(contacter, values, selection, selectionArgs);
break;
case CONTACTER:
long sid = ContentUris.parseId(uri);
String where = TextUtils.isEmpty(selection) ? contacterid=?
: selection + and contacterid=?;
String[] params = new String[] { String.valueOf(sid) };
if (!TextUtils.isEmpty(selection) && selectionArgs != null) {
params = new String[selectionArgs.length + 1];
for (int i = 0; i < selectionArgs.length; i++) {
params[i] = selectionArgs[i];
}
params[selectionArgs.length] = String.valueOf(sid);
}
count = db.delete(contacter, where, params);
break;
default:
throw new IllegalArgumentException(Unknow Uri: + uri);
}
return count;
}
}
第四步、新建Activity ContentProviderActivity.java
/**
*
*/
package com.figo.helloworld;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.GridView;
import android.widget.SimpleAdapter;
/**
* @author zhuzhifei
*
*/
public class ContentProviderActivity extends Activity implements
OnClickListener {
private Button btnAdd;
private Button btnDelete;
private Button btnUpdate;
private Button btnQuery;
private ContentResolver resolver;
private int count;//行數
private String contacterid;//選中的
private List