如何创建Content Provider

Content Provider用来管理数据的集中存储库,Content Provider主要功能是使应用的数据可以被其他应用访问。


一、在实现Content Provider时,先考虑一下是否有必要使用Content Provider来管理数据。一般在满足一下几种情况下:

1.    需要为其他应用程序提供复杂的数据或者文件
2.    允许其他应用程序拷贝自己的应用程序复杂数据
3.    需要提供在搜索框架下提供自己的搜索建议
另外,没有必要为自己应用实现一个Content Provider使用SQLite DataBase来管理数据。

 二、如何创建一个Provider:
1.    设计原始数据,Content Provider提供两方面的数据:
a.    文件数据:如图片、视频、音频文件等,将文件保存在应用的空间中,Content Provider需要为其提供文件句柄供其他应用访问使用。
b.    结构数据,即可以保存在数据库、数组和类似结构的数据。数据将保存在一个兼容形势的表中,行表示一个实体,列表示实体的属性等。通常的做法是将这类数据保存在一个SQLite DataBase中。
2.    定义Provider的authority 、URIS和字段,如果需要Provider处理intent,定义action、extras、和flags,以及定义需要访问应用数据的权限。可以考虑将这些常量写在一个独立的类中,即Contract class。
3.    定义一个ContentProvider的子类,并实现它的方法。这个类就是ContentProvider的子类你的应用数据和其它android系统交互的接口。

4.    添加其它项,如一些示例数据、或者实现一个可以同步Provider和运数据的AbstractThreadedSyncAdapter的子类。


三、如何实现一个ContentProvider,其中上面提到1、4步忽略

2.实现Contract class

package com.example.logcontentprovider;

import android.net.Uri;

public class LogInfo {
	
	//db info
	public static final String DB_NAME = "errordb";
	public static final String TABLE_ANR_NAME = "anrinfo";
	public static final String TABLE_CRASH_NAME = "crashinfo";
	public static final int VERSION = 1;
	
	//column name for anr
	public static String ANR_ID = "anr_id";
	public static final String ANR_ACTIVITY = "anr_activity";
	public static final String ANR_CAUSE = "anr_cause";
	public static final String ANR_CPU = "anr_cpu";
	
	//column name for crash
	public static String CRASH_ID = "crash_id";
	public static final String EXCEPTION_CLASSNAME = "exception_classname";
	public static final String EXCEPTION_MESSAGE = "eccption_messge";
	public static final String THROW_FILENAME = "throw_filename";
	public static final String THROW_CLASSNAME = "throw_classname";
	public static final String THROW_METHODNAME = "throw_methodname";
	public static final String THROW_LINENUMBER = "throw_linenumber";
	
	//define authority eg:com.example.<appname>.provider 
	public static final String AUTOHORITY = "com.example.logcontentprovider";
	
	//define URIs eg: content://<authority>/<path> or  content://<authority>/<path>/<id> 
	public static final Uri ANR_CONTENT_URI = Uri.parse("content://" + AUTOHORITY + "/" +TABLE_ANR_NAME);

	public static final Uri CRASH_CONTENT_URI = Uri.parse("content://" + AUTOHORITY + "/" +TABLE_CRASH_NAME);

}

3.    定义一个ContentProvider的子类

package com.example.logcontentprovider;

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.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

public class LogContentProvider extends ContentProvider{
	
	private static final UriMatcher sUriMatcher;
	
	static{
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(LogInfo.AUTOHORITY, LogInfo.TABLE_CRASH_NAME, 1);
		sUriMatcher.addURI(LogInfo.AUTOHORITY, LogInfo.TABLE_CRASH_NAME + "/#", 2);
		
		sUriMatcher.addURI(LogInfo.AUTOHORITY, LogInfo.TABLE_ANR_NAME, 3);
		sUriMatcher.addURI(LogInfo.AUTOHORITY, LogInfo.TABLE_ANR_NAME + "/#", 4);
	}

	//create anr table
	private static final String SQL_CREATE_TABLE_ANR = "CREATE TABLE "
			+ LogInfo.TABLE_ANR_NAME + "(" + LogInfo.ANR_ID
			+ " integer primary key autoincrement not null,"
			+ LogInfo.ANR_ACTIVITY + " text," + LogInfo.ANR_CAUSE
			+ " text," + LogInfo.ANR_CPU + " text);";
	
	//create crash table
	private static final String SQL_CREATE_TABLE_CRASH = "CREATE TABLE "
			+ LogInfo.TABLE_CRASH_NAME + "(" + LogInfo.CRASH_ID
			+ " integer primary key autoincrement not null,"
			+ LogInfo.EXCEPTION_CLASSNAME + " text,"
			+ LogInfo.EXCEPTION_MESSAGE + " text,"
			+ LogInfo.THROW_CLASSNAME + " text,"
			+ LogInfo.THROW_FILENAME + " text,"
			+ LogInfo.THROW_METHODNAME + " text,"
			+ LogInfo.THROW_LINENUMBER + " integer);";
	
	private MainDatabaseHelper mOpenHelper;
	private SQLiteDatabase db;
	
	
	public LogContentProvider() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		
		db = mOpenHelper.getWritableDatabase();
		int count = 0;
		String id = "";
		switch (sUriMatcher.match(uri)){
		case 1:
			count = db.delete(LogInfo.TABLE_CRASH_NAME, selection,
					selectionArgs);
			break;
		case 2:
			id = uri.getPathSegments().get(1);
			count = db.delete(LogInfo.TABLE_CRASH_NAME, 2
					+ " = "
					+ id
					+ (!TextUtils.isEmpty(LogInfo.CRASH_ID = "?") ? "AND("
							+ selection + ')' : ""), selectionArgs);
			break;
		case 3:
			count = db.delete(LogInfo.TABLE_ANR_NAME, selection,
					selectionArgs);
			break;
		case 4:
			id = uri.getPathSegments().get(1);
			count = db.delete(LogInfo.TABLE_ANR_NAME, 2
					+ " = "
					+ id
					+ (!TextUtils.isEmpty(LogInfo.ANR_ID = "?") ? "AND("
							+ selection + ')' : ""), selectionArgs);
			break;
		default:
			Log.e("zy", "not usfull uri = " + uri);
		}
		
		getContext().getContentResolver().notifyChange(uri, null);
		
		return count;
	}

	@Override
	public String getType(Uri uri) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		
		db = mOpenHelper.getWritableDatabase();
		
		long rowId = 0 ;
		
		Uri insertUri = null;
		
		switch (sUriMatcher.match(uri)){
		case 1:
			rowId = db.insert(LogInfo.TABLE_CRASH_NAME, LogInfo.CRASH_ID, values);
			
			if(rowId > 0){
				insertUri = ContentUris.withAppendedId(LogInfo.ANR_CONTENT_URI, rowId);
			}
			
			break;
			
		case 2:
			Log.e("zy", "this uri is not usfull for insert, uri = " + uri );
			break;
			
		case 3:
			rowId = db.insert(LogInfo.TABLE_ANR_NAME, LogInfo.ANR_ID, values);
			
			if(rowId > 0){
				insertUri = ContentUris.withAppendedId(LogInfo.ANR_CONTENT_URI, rowId);
			}
			
			break;
			
		case 4:
			Log.e("zy", "this uri is not usfull for insert, uri = " + uri );
			break;
			
		default:
			
			Log.e("zy", "not usfull uri = " + uri);
		}
		
		if(rowId > 0){
			
			getContext().getContentResolver().notifyChange(insertUri, null);
		}
		
		return insertUri;
	}

	@Override
	public boolean onCreate() {
		
		mOpenHelper = new MainDatabaseHelper(this.getContext());
		return false;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		
		db = mOpenHelper.getWritableDatabase();
		
		Cursor c = null;
		String id = "";

		switch (sUriMatcher.match(uri)) {
		case 1:

			c = db.query(LogInfo.TABLE_CRASH_NAME, projection, selection,
					selectionArgs, null, null, sortOrder);
			break;
		case 2:

			id = uri.getPathSegments().get(1);
			c = db.query(LogInfo.TABLE_CRASH_NAME, projection, LogInfo.ANR_ID
					+ "="
					+ id
					+ (!TextUtils.isEmpty(selection) ? "AND(" + selection + ')'
							: ""), selectionArgs, null, null, sortOrder);
			break;
		case 3:

			c = db.query(LogInfo.TABLE_ANR_NAME, projection, selection,
					selectionArgs, null, null, sortOrder);
			break;			
		case 4:

			c = db.query(LogInfo.TABLE_ANR_NAME, projection, LogInfo.ANR_ID
					+ "="
					+ id
					+ (!TextUtils.isEmpty(selection) ? "AND(" + selection + ')'
							: ""), selectionArgs, null, null, sortOrder);
			break;			
		default:
			
			Log.e("zy", "not usfull uri = " + uri);
		}

		return c;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		db = mOpenHelper.getWritableDatabase();
		
		int count = 0;
		String id = "";
		
		switch (sUriMatcher.match(uri)) {
		case 1:
			count = db.update(LogInfo.TABLE_CRASH_NAME, values, selection,
					selectionArgs);
			break;
		case 2:
			id = uri.getPathSegments().get(1);
			count = db.update(
					LogInfo.TABLE_CRASH_NAME,
					values,
					LogInfo.CRASH_ID
							+ "="
							+ id
							+ (!TextUtils.isEmpty(selection) ? "AND("
									+ selection + ")" : ""), selectionArgs);
			break;

		case 3:
			count = db.update(LogInfo.TABLE_ANR_NAME, values, selection,
					selectionArgs);
			break;
		case 4:
			id = uri.getPathSegments().get(1);
			count = db.update(
					LogInfo.TABLE_ANR_NAME,
					values,
					LogInfo.ANR_ID
							+ "="
							+ id
							+ (!TextUtils.isEmpty(selection) ? "AND("
									+ selection + ")" : ""), selectionArgs);
			break;
			
		default:
			
			Log.e("zy", "not usfull uri = " + uri);
			
		}
		
		return count;
	}

	
	protected static final class MainDatabaseHelper extends SQLiteOpenHelper {

		public MainDatabaseHelper(Context context) {
			
			super(context, LogInfo.DB_NAME, null, LogInfo.VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			
			db.execSQL(SQL_CREATE_TABLE_CRASH);
			db.execSQL(SQL_CREATE_TABLE_ANR);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			// TODO Auto-generated method stub
			
		}
		
	}
}

另外:别忘了在AndroidManifest.xml文件中注册:

        <provider android:name="com.example.logcontentprovider.LogContentProvider" 
            android:authorities="com.example.logcontentprovider"
            android:permission="true">
        </provider>

四、使用ContentResolver来访问ContentProvider中的数据库:

 private Uri saveErrorInfo(){       
      ContentResolver resolver =  getContentResolver();
      values.put(LogInfo.EXCEPTION_CLASSNAME, “a1”);
      values.put(LogInfo.EXCEPTION_MESSAGE,“a2”);
      values.put(LogInfo.THROW_CLASSNAME, “a3”);
      values.put(LogInfo.THROW_FILENAME, “a4”);
      values.put(LogInfo.THROW_METHODNAME, “a5”);
      values.put(LogInfo.THROW_LINENUMBER, “a6”);
      Uri uri = Uri.parse("content://com.example.logcontentprovider/crashinfo");
      return resolver.insert(uri, values); //返回insert成功后对应行的Uri eg:content://<authority>/<path>/<id>
}

成功后可以导出db文件查看到插入到数据库中的数据.


以上,即完成了一个ContentProvider的创建和使用过程。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值