ContentProvider作为四大组件之一大家应该或多或少有接触过。其主要功能是封装数据库的增删改查的操作,并可以向外提供接口,供其它应用程序访问本应用数据库里面的数据。本文代码贴的多些,大家可以在文章底部把代码下载下来结合着看,主要是讲解下如何创建自己的ContentProvider。
1:首先我们创建一个类继承至ContentProvider。并且需要实现query,getType,insert,delete,update几个函数。后面提供具体实现
public class MyContentProvider extends ContentProvider{
}
2:由于ContentProvider的增删改查实际上是对数据库的增删改查,所以需要一个操作数据库的类。里面在SD卡根目录下创建了一个叫做test.db的数据库,因为数据库默认路径在系统目录下,如果手机没有root,我们是查看不到该数据库的。所以把它的路径设置到sd卡上。这样大家可以通过工具sqlitestudio来查看数据库里面的内容
class SqliteHelper extends SQLiteOpenHelper{
public final static String DB_NAME = android.os.Environment.getExternalStorageDirectory().getAbsolutePath()+"/test.db";
public final static int DB_VERSION = 1;
public final static String DB_ID = "id"; //id
public final static String DB_TABLE = "test"; //表名称为test
public final static String DB_TABLE_NAME = "name";//表中有个字段为name
public SqliteHelper(Context context)
{
super(context,DB_NAME,null,DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DB_TABLE + " ("
+ DB_ID + " INTEGER PRIMARY KEY,"
+ DB_TABLE_NAME + " TEXT"
+ ");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+DB_TABLE);
onCreate(db);
}
}
3:创建UriMatcher对象及数据库操作对象。在增删改查的时候会从调用端传递uri对象过来,在ContentProvider的增删改查的函数里面,我们需要根据该uri来判断,是要操作一条数据,还是操作所有符合条件的数据。
public class MyContentProvider extends ContentProvider{
private SqliteHelper mHelper;
public static final String strUri = "com.example.testcontentprovider";
//定义的uri中间部分。如content://com.example.testcontentprovider/test
private static final int TEST = 101;
private static final int TESTS = 102;
private static final UriMatcher uriMatcher;
static
{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(strUri, "test", TESTS);
//操作所有符合条件的数据,如删除所有name="aa"的数据。
uriMatcher.addURI(strUri, "test/#", TEST);
//操作唯一符合条件的数据,如删除id=1的数据
//如客户端传递的uri=content://com.example.testcontentprovider/test,那么调用uriMatcher.match(uri)时返回TESTS
//如客户端传递的uri=content://com.example.testcontentprovider/test/10,那么调用uriMatcher.match(uri)时返回TEST
}
@Override
public boolean onCreate() {
mHelper = new SqliteHelper(getContext());
return false;
}
}
4:实现query查询函数。
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = mHelper.getReadableDatabase();
switch(uriMatcher.match(uri))
{
case TEST: //例如uri=content://com.example.testcontentprovider/test/10
long id = ContentUris.parseId(uri); //此处得到id=10
String where = "id="+id;
where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : "";
// 把其它条件附加上
return db.query(SqliteHelper.DB_TABLE, projection, where, selectionArgs, null, null, sortOrder);
//查询id=10的数据
case TESTS:
//例如uri=content://com.example.testcontentprovider/test 查询所有符合条件的数据
return db.query(SqliteHelper.DB_TABLE, projection, selection, selectionArgs, null, null, sortOrder);
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues initvalues) {
SQLiteDatabase db = mHelper.getWritableDatabase();
ContentValues values;
if(initvalues != null)
{
values = new ContentValues(initvalues);
}else
{
values = new ContentValues();
}
switch( uriMatcher.match(uri))
{
case TEST:
break;
case TESTS:
if(values.containsKey(SqliteHelper.DB_TABLE_NAME) == false)
{
values.put(SqliteHelper.DB_TABLE_NAME, "");
}
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
long rowid = db.insert(SqliteHelper.DB_TABLE, null, values);
// 返回的是记录的行号,主键为int,实际上就是主键值
if(rowid > 0)
{
Uri noteuri = ContentUris.withAppendedId(uri, rowid);
return noteuri;
}
throw new SQLException("Failed to insert row into " + uri);
}
6:实现delete删除函数
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = mHelper.getWritableDatabase();
int count = 0;
switch( uriMatcher.match(uri))
{
case TEST: //删除指定数据
long id = ContentUris.parseId(uri);
String where = "id="+id;
where += !TextUtils.isEmpty(selection)?" and ("+selection+")" : "";
count = db.delete(SqliteHelper.DB_TABLE, where, selectionArgs);
break;
case TESTS: //删除所有数据
count = db.delete(SqliteHelper.DB_TABLE, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
db.close();
return count;
}
7:实现update修改函数
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = mHelper.getWritableDatabase();
int count = 0;
switch( uriMatcher.match(uri))
{
case TEST:
long id = ContentUris.parseId(uri);
String where = "id="+id;
where += !TextUtils.isEmpty(selection)?" and ("+selection+")" : "";
count = db.update(SqliteHelper.DB_TABLE,values, where, selectionArgs);
break;
case TESTS:
db.update(SqliteHelper.DB_TABLE, values, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
db.close();
return count;
}
8:实现getType函数。如果是单一数据那么用vnd.android.cursor.item。如果是数据集那么用vnd.android.cursor.dir。该函数在本例中暂时没有实际用到
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/com.example.testcontentproviders";
public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/com.example.testcontentprovider";
@Override
public String getType(Uri uri) {
switch(uriMatcher.match(uri))
{
case TEST:
return CONTENT_TYPE_ITEM;
case TESTS:
return CONTENT_TYPE;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
由于要读写数据库和sd卡,所以在ContentProvider的程序中还需要添加对应权限
在另外一个app AndroidManifest.xml里面添加
//有读的权限
//有写的权限
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
Uri mUri_insert = Uri.parse("content://"+MyContentProvider.strUri+"/test");
Uri mUris_del = Uri.parse("content://"+MyContentProvider.strUri+"/test/1");
//删除id为1的数据
Uri mUris_query = Uri.parse("content://"+MyContentProvider.strUri+"/test/2");
//查询id为2的数据
Uri mUris_update = Uri.parse("content://"+MyContentProvider.strUri+"/test/3");
//修改id为2的数据
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void insert(View v)
{
ContentResolver cr = this.getContentResolver();
ContentValues value = new ContentValues();
value.put(SqliteHelper.DB_TABLE_NAME, "test1");
Uri uri = cr.insert(mUri_insert, value);
}
public void delete(View v)
{
ContentResolver cr = this.getContentResolver();
int m = cr.delete(mUris_del, null, null);
}
public void query(View v)
{
ContentResolver cr = this.getContentResolver();
Cursor c= cr.query(mUris_query, null, null, null, null);
if(c.moveToFirst() == false)
{
return;
}
int nameindex = c.getColumnIndex("name");
String strname = c.getString(nameindex);
Toast.makeText(this, strname, Toast.LENGTH_SHORT).show();
c.close();
}
public void modify(View v)
{
ContentResolver cr = this.getContentResolver();
ContentValues value = new ContentValues();
value.put(SqliteHelper.DB_TABLE_NAME, "testupdate");
cr.update(mUris_update, value, null, null);
}
}
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.text.TextUtils;
public class MyContentProvider extends ContentProvider{
private SqliteHelper mHelper;
private static final UriMatcher uriMatcher;
public static final String strUri = "com.example.testcontentprovider";
private static final int TEST = 101;
private static final int TESTS = 102;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/com.example.testcontentproviders";
public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/com.example.testcontentprovider";
static
{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(strUri, "test", TESTS);
uriMatcher.addURI(strUri, "test/#", TEST);
}
@Override
public boolean onCreate() {
mHelper = new SqliteHelper(getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = mHelper.getReadableDatabase();
switch(uriMatcher.match(uri))
{
case TEST:
long id = ContentUris.parseId(uri);
String where = "id="+id;
where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : "";// 把其它条件附加上
return db.query(SqliteHelper.DB_TABLE, projection, where, selectionArgs, null, null, sortOrder);
case TESTS:
return db.query(SqliteHelper.DB_TABLE, projection, selection, selectionArgs, null, null, sortOrder);
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public String getType(Uri uri) {
switch(uriMatcher.match(uri))
{
case TEST:
return CONTENT_TYPE_ITEM;
case TESTS:
return CONTENT_TYPE;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues initvalues) {
SQLiteDatabase db = mHelper.getWritableDatabase();
ContentValues values;
if(initvalues != null)
{
values = new ContentValues(initvalues);
}else
{
values = new ContentValues();
}
switch( uriMatcher.match(uri))
{
case TEST:
break;
case TESTS:
if(values.containsKey(SqliteHelper.DB_TABLE_NAME) == false)
{
values.put(SqliteHelper.DB_TABLE_NAME, "");
}
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
long rowid = db.insert(SqliteHelper.DB_TABLE, null, values); // 返回的是记录的行号,主键为int,实际上就是主键值
if(rowid > 0)
{
Uri noteuri = ContentUris.withAppendedId(uri, rowid);
return noteuri;
}
throw new SQLException("Failed to insert row into " + uri);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = mHelper.getWritableDatabase();
int count = 0;
switch( uriMatcher.match(uri))
{
case TEST: //删除指定数据
long id = ContentUris.parseId(uri);
String where = "id="+id;
where += !TextUtils.isEmpty(selection)?" and ("+selection+")" : "";
count = db.delete(SqliteHelper.DB_TABLE, where, selectionArgs);
break;
case TESTS: //删除所有数据
count = db.delete(SqliteHelper.DB_TABLE, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
db.close();
return count;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = mHelper.getWritableDatabase();
int count = 0;
switch( uriMatcher.match(uri))
{
case TEST:
long id = ContentUris.parseId(uri);
String where = "id="+id;
where += !TextUtils.isEmpty(selection)?" and ("+selection+")" : "";
count = db.update(SqliteHelper.DB_TABLE,values, where, selectionArgs);
break;
case TESTS:
db.update(SqliteHelper.DB_TABLE, values, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
db.close();
return count;
}
}
class SqliteHelper extends SQLiteOpenHelper{
public final static String DB_NAME = android.os.Environment.getExternalStorageDirectory().getAbsolutePath()+"/test.db";
public final static int DB_VERSION = 1;
public final static String DB_ID = "id";
public final static String DB_TABLE = "test";
public final static String DB_TABLE_NAME = "name";
public SqliteHelper(Context context)
{
super(context,DB_NAME,null,DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DB_TABLE + " ("
+ DB_ID + " INTEGER PRIMARY KEY,"
+ DB_TABLE_NAME + " TEXT"
+ ");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+DB_TABLE);
onCreate(db);
}
}
源码下载
ContentProvider 实例详解一(创建一个自己的ContentProvider)
ContentProvider 实例详解二(观察者模式监测数据的变化)