ContentProvider 实例详解一(创建一个自己的ContentProvider)

          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);
		}
		
	}
5:实现insert插入函数
	@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);
		}
	}
9:MyContentProvider写好了那么剩下的就看如何调用MyContentProvider了。这有分为在当前app里面调用和在另外一个app里面调用
在当前app里面调用和在另外app里面调用方式是一样的,唯一的是要配置两个app里面的provider权限。
在当前app AndroidManifest.xml里面添加
        <provider
            android:name="com.example.testcontentprovider.MyContentProvider"
            android:authorities="com.example.testcontentprovider"
            android:exported="true"
            android:readPermission="a.r"     //a.r  b.w 可以自己定义
            android:writePermission="b.w" >
        </provider>

由于要读写数据库和sd卡,所以在ContentProvider的程序中还需要添加对应权限
  <uses-permission android:name="android.permission.READ_PERSON_DB" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
在另外一个app  AndroidManifest.xml里面添加
<pre name="code" class="java"><uses-permission android:name="a.r"/>  //有读的权限
<uses-permission android:name="b.w"/>  //有写的权限
 
  
调用MyContentProvider MainActivity.java源码:
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);
    }
    
    
}

10:MyContentProvider.java实现过程
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 实例详解二(观察者模式监测数据的变化)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值