Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android開發步步為營之34:四大組件之ContentProvider

android開發步步為營之34:四大組件之ContentProvider

編輯:關於Android編程

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> list = new ArrayList>();



//Uri uri=Uri.parse(content://com.figo.helloworld.MyContentProvider/contacter/#);
Uri uri=Uri.parse(content://com.figo.helloworld.MyContentProvider/contacter);
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
this.setContentView(R.layout.contentproviderview);
resolver=this.getContentResolver();
btnAdd=(Button)findViewById(R.id.btnadd);
btnDelete=(Button)findViewById(R.id.btndelete);
btnUpdate=(Button)findViewById(R.id.btnupdate);
btnQuery=(Button)findViewById(R.id.btnquery);
btnAdd.setOnClickListener(this);
btnDelete.setOnClickListener(this);
btnUpdate.setOnClickListener(this);
btnQuery.setOnClickListener(this);
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub

switch (v.getId()) {
case R.id.btnadd://增
count=count+1;
ContentValues cvadd=new ContentValues();
cvadd.put(name, 朋友+count);
cvadd.put(age, 32);
Uri uriadd=resolver.insert(uri, cvadd);
long countnew=ContentUris.parseId(uriadd);
count=Integer.parseInt(String.valueOf(countnew));
query();
break;
case R.id.btndelete://刪
String[] deleteparas=new String[1];
deleteparas[0]=String.valueOf(contacterid);
resolver.delete(uri, contacterid=?, deleteparas);
query();
break;
case R.id.btnupdate://改
String[] updateparas=new String[1];
updateparas[0]=String.valueOf(contacterid);
ContentValues cvupdate=new ContentValues();
cvupdate.put(name, 朋友啊朋友+contacterid);
cvupdate.put(age, 30);
resolver.update(uri,cvupdate, contacterid=?, updateparas);
query();
break;
case R.id.btnquery://查
query();
count=list.size();
break;
default:
break;
}
}
//查詢方法
private void query()
{
//Cursor cursor=resolver.query(uri, projection, selection, selectionArgs, contacterid desc);
list.clear();//先清理
Cursor cursor=resolver.query(uri, new String[]{contacterid,name,age}, null, null, contacterid desc);
while(cursor.moveToNext())
{
Map map = new HashMap();
map.put(contacterid, cursor.getString(0));
map.put(img, R.drawable.icon);
map.put(name, cursor.getString(1));
map.put(age, cursor.getString(2));
list.add(map);
}
// 生成適配器
SimpleAdapter adapter = new SimpleAdapter(this, list,
R.layout.friendview, new String[] { img,contacterid, name, age },
new int[] { R.id.imgHead,R.id.tvPersonId, R.id.tvName, R.id.tvAge });
GridView gridView = (GridView) findViewById(R.id.gvContentProvider);
gridView.setAdapter(adapter);
gridView.setColumnWidth(200);
// 添加點擊行事件
gridView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
// 在本例中arg2=arg3
Map item = (Map) parent.getItemAtPosition(position);
// 顯示所選Item的ItemText
setTitle(item.get(name).toString());
contacterid=item.get(contacterid).toString();
}
});
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}

@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
}

@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
}

@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
}

@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
}

@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
}
}

第五步、AndroidManifest.xml注冊之前創建的MyContentProvider.java和ContentProviderActivity.java

package=com.figo.helloworld android:versionCode=1 android:versionName=1.0>





android:authorities=com.figo.helloworld.MyContentProvider >






第六步、運行效果


\
在手機或者模擬器裡面安裝了helloworld應用之後,Sudoku應用中,同理將helloworld的ContentProviderActivity.java、contentproviderview.xml、friendview.xml拷過來,通過resolver=this.getContentResolver();獲取到helloworld暴露出來的com.figo.helloworld.MyContentProvider就發現直接可以操作helloworld裡面的數據了。所以一個應用需要向另外一個應用暴露數據的時候,我們就可以方便的使用ContentProvider來實現了。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved