首页 > 代码库 > android开发步步为营之34:四大组件之ContentProvider
android开发步步为营之34:四大组件之ContentProvider
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中的注册
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.figo.helloworld" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<provider android:name="com.figo.helloworld.MyContentProvider"
android:authorities="com.figo.helloworld.MyContentProvider" >
</provider>
<activity android:name=".ContentProviderActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
实践操作
这个实例里面,在helloworld应用里面,我们创建一个名为联系人contacter的sqlitedatabase数据库,里面有一张表联系人contacter,包含字段联系人contacterid编号,name姓名,age年龄3个字段。然后通过contentprovider实现对sqlitedatabase数据的增删改查操作,同时使用gridview将数据展现出来,然后在另外一个应用里面Sudoku里面通过helloworld提供的contentprovider实现对helloworld应用contacter数据库的操作,从而实现数据的共享。
Helloworld应用
第一步、新建页面contentproviderview.xml,friendview.xml
contentproviderview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:text="@string/contentprovider"></TextView>
<Button android:id="@+id/btnadd" android:layout_width="wrap_content" android:text="@string/add" android:layout_height="wrap_content" android:layout_below="@+id/textView1" android:layout_alignParentLeft="true" android:layout_marginTop="15dp"></Button>
<Button android:id="@+id/btndelete" android:layout_width="wrap_content" android:text="@string/delete" android:layout_height="wrap_content" android:layout_alignTop="@+id/btnadd" android:layout_toRightOf="@+id/btnadd" android:layout_marginLeft="30dp"></Button>
<Button android:id="@+id/btnupdate" android:layout_width="wrap_content" android:text="@string/update" android:layout_height="wrap_content" android:layout_alignTop="@+id/btndelete" android:layout_alignRight="@+id/textView1"></Button>
<Button android:id="@+id/btnquery" android:layout_width="wrap_content" android:text="@string/query" android:layout_height="wrap_content" android:layout_alignTop="@+id/btnupdate" android:layout_toRightOf="@+id/btnupdate" android:layout_marginLeft="24dp"></Button>
<LinearLayout android:layout_below="@+id/btnadd" android:layout_height="fill_parent" android:layout_width="fill_parent" >
<ScrollView android:id="@+id/scrollView1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#f66" android:layout_alignParentLeft="true" android:layout_marginTop="40dp" android:layout_alignParentRight="true">
<LinearLayout android:layout_height="fill_parent" android:layout_width="fill_parent" >
<GridView android:id="@+id/gvContentProvider" android:columnWidth="100dp" android:layout_width="wrap_content" android:layout_height="300dp"></GridView>
</LinearLayout>
</ScrollView>
</LinearLayout>
</RelativeLayout>
friendview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:id="@+id/imgHead" android:layout_width="wrap_content" android:src=http://www.mamicode.com/"@drawable/icon" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentLeft="true">
<TextView android:id="@+id/tvAge" android:layout_width="wrap_content" android:text="年龄" android:layout_height="wrap_content" android:layout_alignTop="@+id/tvName" android:layout_alignParentRight="true" android:layout_marginRight="43dp"></TextView>
<TextView android:layout_width="wrap_content" android:text="编号" android:layout_height="wrap_content" android:layout_alignBottom="@+id/imgHead" android:layout_toRightOf="@+id/imgHead" android:layout_marginBottom="14dp" android:id="@+id/tvPersonId"></TextView>
<TextView android:id="@+id/tvName" android:layout_width="wrap_content" android:text="姓名" android:layout_height="wrap_content" android:layout_alignTop="@+id/tvPersonId" android:layout_centerHorizontal="true"></TextView>
</RelativeLayout>
第二步、新建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<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
//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<String, Object> map = new HashMap<String, Object>();
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<String, Object> item = (Map<String, Object>) 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
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.figo.helloworld" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<provider android:name="com.figo.helloworld.MyContentProvider"
android:authorities="com.figo.helloworld.MyContentProvider" >
</provider>
<activity android:name=".ContentProviderActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
第六步、运行效果
在手机或者模拟器里面安装了helloworld应用之后,Sudoku应用中,同理将helloworld的ContentProviderActivity.java、contentproviderview.xml、friendview.xml拷过来,通过resolver=this.getContentResolver();获取到helloworld暴露出来的com.figo.helloworld.MyContentProvider就发现直接可以操作helloworld里面的数据了。所以一个应用需要向另外一个应用暴露数据的时候,我们就可以方便的使用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中的注册
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.figo.helloworld" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<provider android:name="com.figo.helloworld.MyContentProvider"
android:authorities="com.figo.helloworld.MyContentProvider" >
</provider>
<activity android:name=".ContentProviderActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
实践操作
这个实例里面,在helloworld应用里面,我们创建一个名为联系人contacter的sqlitedatabase数据库,里面有一张表联系人contacter,包含字段联系人contacterid编号,name姓名,age年龄3个字段。然后通过contentprovider实现对sqlitedatabase数据的增删改查操作,同时使用gridview将数据展现出来,然后在另外一个应用里面Sudoku里面通过helloworld提供的contentprovider实现对helloworld应用contacter数据库的操作,从而实现数据的共享。
Helloworld应用
第一步、新建页面contentproviderview.xml,friendview.xml
contentproviderview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:text="@string/contentprovider"></TextView>
<Button android:id="@+id/btnadd" android:layout_width="wrap_content" android:text="@string/add" android:layout_height="wrap_content" android:layout_below="@+id/textView1" android:layout_alignParentLeft="true" android:layout_marginTop="15dp"></Button>
<Button android:id="@+id/btndelete" android:layout_width="wrap_content" android:text="@string/delete" android:layout_height="wrap_content" android:layout_alignTop="@+id/btnadd" android:layout_toRightOf="@+id/btnadd" android:layout_marginLeft="30dp"></Button>
<Button android:id="@+id/btnupdate" android:layout_width="wrap_content" android:text="@string/update" android:layout_height="wrap_content" android:layout_alignTop="@+id/btndelete" android:layout_alignRight="@+id/textView1"></Button>
<Button android:id="@+id/btnquery" android:layout_width="wrap_content" android:text="@string/query" android:layout_height="wrap_content" android:layout_alignTop="@+id/btnupdate" android:layout_toRightOf="@+id/btnupdate" android:layout_marginLeft="24dp"></Button>
<LinearLayout android:layout_below="@+id/btnadd" android:layout_height="fill_parent" android:layout_width="fill_parent" >
<ScrollView android:id="@+id/scrollView1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#f66" android:layout_alignParentLeft="true" android:layout_marginTop="40dp" android:layout_alignParentRight="true">
<LinearLayout android:layout_height="fill_parent" android:layout_width="fill_parent" >
<GridView android:id="@+id/gvContentProvider" android:columnWidth="100dp" android:layout_width="wrap_content" android:layout_height="300dp"></GridView>
</LinearLayout>
</ScrollView>
</LinearLayout>
</RelativeLayout>
friendview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:id="@+id/imgHead" android:layout_width="wrap_content" android:src=http://www.mamicode.com/"@drawable/icon" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentLeft="true">
<TextView android:id="@+id/tvAge" android:layout_width="wrap_content" android:text="年龄" android:layout_height="wrap_content" android:layout_alignTop="@+id/tvName" android:layout_alignParentRight="true" android:layout_marginRight="43dp"></TextView>
<TextView android:layout_width="wrap_content" android:text="编号" android:layout_height="wrap_content" android:layout_alignBottom="@+id/imgHead" android:layout_toRightOf="@+id/imgHead" android:layout_marginBottom="14dp" android:id="@+id/tvPersonId"></TextView>
<TextView android:id="@+id/tvName" android:layout_width="wrap_content" android:text="姓名" android:layout_height="wrap_content" android:layout_alignTop="@+id/tvPersonId" android:layout_centerHorizontal="true"></TextView>
</RelativeLayout>
第二步、新建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<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
//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<String, Object> map = new HashMap<String, Object>();
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<String, Object> item = (Map<String, Object>) 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
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.figo.helloworld" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<provider android:name="com.figo.helloworld.MyContentProvider"
android:authorities="com.figo.helloworld.MyContentProvider" >
</provider>
<activity android:name=".ContentProviderActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
第六步、运行效果
在手机或者模拟器里面安装了helloworld应用之后,Sudoku应用中,同理将helloworld的ContentProviderActivity.java、contentproviderview.xml、friendview.xml拷过来,通过resolver=this.getContentResolver();获取到helloworld暴露出来的com.figo.helloworld.MyContentProvider就发现直接可以操作helloworld里面的数据了。所以一个应用需要向另外一个应用暴露数据的时候,我们就可以方便的使用ContentProvider来实现了。
android开发步步为营之34:四大组件之ContentProvider
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。