自定义ContentProvider

3.其他几个就不详细介绍了,说下今天的重点ContentProvider

    创建一个可对数据库进行操作的ContentProvider我们先要了解涉及到的知识点:
    (1)Parcelable(实体类数据一般会用在进程之间通信)
           http://my.oschina.net/zhoulc/blog/172163
    (2)BaseColumns,这个类只是提供了两个字段,一个是"_id"一个是"_count",便于调用数据库时导致拼写错误,你也可以扩展它,或者自定义这么个,然后直接调用它的常量名,防止写sql语句时把列名拼错。

package android.provider; public interface BaseColumns { /** * The unique ID for a row. * <P>Type: INTEGER (long)</P> */ public static final String _ID = "_id"; /** * The count of rows in a directory. * <P>Type: INTEGER</P> */ public static final String _COUNT = "_count"; }
    (3)SQLiteOpenHelper,包装了数据库的创建、打开、更新的抽象类,通过实现和使用SQLiteOpenHandle可以隐去数据库打开的之前判断数据库是否需要创建或更新的逻辑。 
            主要实现三个方法 
            创建数据库:public DatabaseHelper(Context context) 
              创建表:public void onCreate(SQLiteDatabase db) 
            更新表:public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
      (4)UriMatcher用来匹配URI。 
            主要实现两个接口: 
              添加需要匹配的URI:MATCHER.addURI(String authority, String path, int code) 进行匹配返回定义的value;MATCHER.match(Uri uri) 
            例: 
                MATCHER.addURI(Information.AUTHORITY, "informations", INFORMATIONS); 
                MATCHER.addURI(Information.AUTHORITY, "informations/#", INFORMATION); 
                # 号为通配符 
                * 号为任意字符 
    (5)ContentUris一个工具类,主要是用来处理使用 "content" 约束的Uri对象,经常用到条件查询某个_ID的数据。 
            主要实现两个接口: 
            static long parseId(Uri contentUri)  将uri中的id解析出来,此方法返回的是一个long型的id。 
            static Uri withAppendedId(Uri contentUri, long id)在指定的uri后面添加一条id 
为指定参数的记录。  
    (6)SQLiteDatabase,这个类是核心类,用于管理和操作SQLite数据库,几乎所有的数据库操作,最终都将由这个类完成。 
    (7)ContentProvider,提供数据库增删改查的接口。 
            主要实现接口: 
            public int delete(Uri uri, String selection, String[] selectionArgs) 
            public String getType(Uri uri) 
            public Uri insert(Uri uri, ContentValues values) 
            public boolean onCreate() 
            public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) 
            public int update(Uri uri, ContentValues values, String selection, 
String[] selectionArgs) 
    (8)ContentResolver接口和ContentProvider类似,两个区别一个是用户是通过ContentResolver调用ContentProvider提供的接口。 
    以上类都只是简单介绍,有兴趣的朋友可以去研究下源码和实现过程。这里主要讲使用过程和一些注意细节。 


4.ContentProvider 在使用过程中需要注意两点: 

    (1)在AndroidManifest.xml里面需要注册这个ContentProvider      
            <provider android:name=".MyProvider" android:authorities="com.zlc.provider.MyProvider" /> 
    (2)当提供给其他进程调用(假如是其他应用),如果当前提供ContentProvider的应用在退出的时候把自己给kill掉了(这个时候ContentProvider也无法使用),则我们需要在AndroidManifest.xml里面再添加一条属性 
            android:process="com.zlc.provider.MyProvider" 
            为该组件指定一个不同的默认进程 


5.下面贴一下具体实现代码

      (1)ContentProvider提供者TestContentProvider.apk 
            实体类:Information.java 
package com.zlc.provider;

import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.BaseColumns;

public class Information implements Parcelable,BaseColumns{
	public final static String AUTHORITY = "com.zlc.provider.MyProvider";
	public final static Uri CONTENT_URI = Uri.parse("content://"+AUTHORITY+"/informations");
	//表字段
	public final static String INFO_ID = "info_id";
	public final static String INFO_NAME = "info_name";
	public final static String INFO_AGE = "info_age";
	
	private String info_id,info_name,info_age;

	public Information(Parcel source){
		info_id = source.readString();
		info_name = source.readString();
		info_age = source.readString();
	}
	public String getInfo_id() {
		return info_id;
	}

	public void setInfo_id(String info_id) {
		this.info_id = info_id;
	}

	public String getInfo_name() {
		return info_name;
	}

	public void setInfo_name(String info_name) {
		this.info_name = info_name;
	}

	public String getInfo_age() {
		return info_age;
	}

	public void setInfo_age(String info_age) {
		this.info_age = info_age;
	}

	@Override
	public int describeContents() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		// TODO Auto-generated method stub
		dest.writeString(info_id);
		dest.writeString(info_name);
		dest.writeString(info_age);
	}
	public final static Parcelable.Creator<Information> CREATOR = new Parcelable.Creator<Information>() {

		@Override
		public Information createFromParcel(Parcel source) {
			// TODO Auto-generated method stub
			return new Information(source);
		}

		@Override
		public Information[] newArray(int size) {
			// TODO Auto-generated method stub
			return new Information[size];
		}
	};
}
            MyProvider.java 
package com.zlc.provider;

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.provider.BaseColumns;
import android.util.Log;

public class MyProvider extends ContentProvider {
	private SQLiteDatabase sqDb;
	private DatabaseHelper helper;
	// 数据库名
	private final static String DATABASE_NAME = "zhoulc.db";
	// 版本
	private static final int DATABASE_VERSION = 1;
	// 表名
	private static final String TABLE_NAME = "Information";
	// 创建表的sql语句
	private final static String CREATE_TABLE = "Create table " + TABLE_NAME
			+ "( "+Information._ID+" integer primary key autoincrement," + Information.INFO_ID
			+ " TEXT," + Information.INFO_NAME + " TEXT," + Information.INFO_AGE
			+ " TEXT);";

	// Declaration Datababsehelper
	private static class DatabaseHelper extends SQLiteOpenHelper {

		public DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			// TODO Auto-generated method stub
			db.execSQL(CREATE_TABLE);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			// TODO Auto-generated method stub
			db.execSQL("DROP TABLE IF EXISTS" + TABLE_NAME);
			onCreate(db);
		}

	}

	// UriMatcher add URI
	private static final UriMatcher MATCHER = new UriMatcher(
			UriMatcher.NO_MATCH);
	private final static int INFORMATIONS = 1;
	private final static int INFORMATION = 2;
	static {
		MATCHER.addURI(Information.AUTHORITY, "informations", INFORMATIONS);
		MATCHER.addURI(Information.AUTHORITY, "informations/#", INFORMATION);
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		sqDb = helper.getWritableDatabase();
		int count = 0;
		switch (MATCHER.match(uri)) {
		case INFORMATIONS:
			count = sqDb.delete(TABLE_NAME, selection, selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
		}
		return count;
	}

	@Override
	public String getType(Uri uri) {
		// TODO Auto-generated method stub
		switch (MATCHER.match(uri)) {
		case INFORMATIONS:
			return "vnd.android.cursor.dir/Information";
		case INFORMATION:
			return "vnd.android.cursor.item/Information";
		default:
			throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		sqDb = helper.getWritableDatabase();
		Uri insertUri = null;
		long rowid = 0;
		switch (MATCHER.match(uri)) {
		case INFORMATIONS:
			rowid = sqDb.insert(TABLE_NAME, Information.INFO_ID, values);
			insertUri = ContentUris.withAppendedId(uri, rowid);
			Log.i("zhoulc", "insert record...values:" + values.toString());
			break;
		default:
			throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
		}
		return insertUri;
	}

	@Override
	public boolean onCreate() {
		// TODO Auto-generated method stub
		helper = new DatabaseHelper(getContext());
		return helper == null ? false : true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
		// TODO Auto-generated method stub
		sqDb = helper.getWritableDatabase();
		switch (MATCHER.match(uri)) {
		case INFORMATIONS:
			Cursor cursor = sqDb.query(TABLE_NAME, projection, selection,
					selectionArgs, null, null, sortOrder);
			return cursor;
		case INFORMATION://条件查询,
			long id = ContentUris.parseId(uri);
			String where = Information._ID + "=" + id; 
			 if (selection != null && !"".equals(selection))  
             {  
                 where = where + " and " + selection;  
             }  
             return sqDb.query(TABLE_NAME, projection, where, selectionArgs, null,  
                 null, sortOrder);  
		default:
			throw new IllegalArgumentException("unknow uri" + uri.toString());
		}
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		sqDb = helper.getWritableDatabase();
		int count = 0;
		switch (MATCHER.match(uri)) {
		case INFORMATIONS:
			count = sqDb.update(TABLE_NAME, values, selection, selectionArgs);
			return count;
		default:
			throw new IllegalArgumentException("unknow uri" + uri.toString());
		}
		
	}

}

            在同一个应用本身里面(进程)测试插入数据:MainActivity.java

package com.zlc.provider;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Bundle;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		Context mContext = MainActivity.this;
		Uri myUri = Information.CONTENT_URI;
		ContentValues values = new ContentValues();
		values.put(Information.INFO_NAME, "zhoulc");
		values.put(Information.INFO_AGE, "99");
		getContentResolver().insert(myUri, values);
		
	}
}
运行结果:   
               

其他应用里面测试(跨进程使用)

            TestActivity.java

package com.zlc.database;

import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;

public class TestActivity extends Activity {
	private ContentResolver resolver;
	public final static String AUTHORITY = "com.zlc.provider.MyProvider";
	private  final static Uri CONTENT_URIS = Uri.parse("content://"+AUTHORITY+"/informations");
	private  final static Uri CONTENT_URI =  Uri.parse("content://"+AUTHORITY+"/informations/1");
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		resolver = getContentResolver();
		//step 1 insert data
		ContentValues values = new ContentValues();
		values.put("info_name", "zhoulc");
		values.put("info_age", "24");
		insert(CONTENT_URIS,values);
		//查询
		Cursor cursor = query(CONTENT_URI,null,null,null,null);
		if(cursor != null){
			if(cursor.moveToFirst()){
				int index[] = new int[]{
					cursor.getColumnIndex("info_id"),
					cursor.getColumnIndex("info_name"),
					cursor.getColumnIndex("info_age")
				};
				do {
					System.out.println(cursor.getString(index[1]));
					System.out.println(cursor.getString(index[2]));
				} while (cursor.moveToNext());
			}
		}
	}
//	该方法用于往ContentProvider添加数据。
	public Uri insert(Uri uri,ContentValues values){
		Uri dst = resolver.insert(uri, values);
		return dst;
	}
//	该方法用于从ContentProvider删除数据。
	public int delete(Uri uri,String where, String[] selectionArgs){
		int colums = resolver.delete(CONTENT_URI, where, selectionArgs);
		return colums;
	}
//	该方法用于更新ContentProvider中的数据。
	public int update(Uri uri,ContentValues values, String where, String[] selectionArgs){
		int colums = resolver.update(CONTENT_URI, values, where, selectionArgs);
		return colums;
	}
//	该方法用于从ContentProvider中获取数据。
	public Cursor query(Uri uri,String[] projection, String where, String[] selectionArgs, String sortOrder){
		Cursor cursor = resolver.query(CONTENT_URI, projection, where, selectionArgs, sortOrder);
		return cursor;
	}
		
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值