`

Android 自定义ContentProvider

阅读更多
自定义 ContentProvider
----------------------------
内容提供器用于与数据源打交道,而内容解析器(ContentResolver)负责操作具体的内容提供器.数据源可以是文件或数据库.多个内容解析器可以同时访问内容提供器,因为它是线程安全的.
一个URI可以确定一个资源,而一个内容提供器可以有多个URI.但所有URI的AUTHORITY相同.
Android没有共享内存,因此要访问另一个进程的数据,必须要通过内容提供器来操作.

1. 继承ContentProvider,并重写所有抽象方法.
Android OS自动调用ContentProvider的onCreate()方法,而数据库是按需启用的.

2. 配置AndroidManifest.xml
<provider android:authorities="tl.android.provider.bookprovider"
      android:name="tl.android.data.TestContentProvider">
</provider>

name: 指定ContentProvider子类的完全类路径.
authorities: 指定ContentProvider惟一标识(推荐:公司名.provider.数据表名+provider)

3. 为内容提供器定义各种常量.
CONTENT_URI
TABLE_NAME
DATABASE_NAME
DATABASE_VERSION
...

4.通过ContentResolver插入数据记录

5. 获取生成的数据库,并查看
*.db 一般在应用目录的 databases 下.
比如:
/data/data/tl.android.apps/databases/books.db

复制数据库到 C:
adb pull /data/data/tl.android.apps/databases/books.db c:\

将生成的books.db拖入sqlite3.exe (在Android SDK tools目录中)

查看数据库中的表
.tables

查看具体的表
select * from table_name;


具体参考代码:
TestContentProvider.java
package tl.android.data;

import java.util.HashMap;

import tl.android.data.TestContentProviderMetaData.BookTableMetaData;
import android.content.ContentProvider;
import android.content.ContentResolver;
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.database.sqlite.SQLiteQueryBuilder;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.TextUtils;
import android.util.Log;

public class TestContentProvider extends ContentProvider {
	public static final String TAG = "amos_tl";
	public DatabaseHelper openHelper = null;
	
         //-- 创建表列名与JavaBean 映射.
	public static HashMap<String, String> sBookProjectionMap = null;
	static{
		sBookProjectionMap = new HashMap<String, String >();
		sBookProjectionMap.put(BookTableMetaData._ID, BookTableMetaData._ID);
		sBookProjectionMap.put(BookTableMetaData.BOOK_NAME, BookTableMetaData.BOOK_NAME);
		sBookProjectionMap.put(BookTableMetaData.BOOK_ISBN, BookTableMetaData.BOOK_ISBN);
		sBookProjectionMap.put(BookTableMetaData.BOOK_AUTHOR, BookTableMetaData.BOOK_AUTHOR);
		sBookProjectionMap.put(BookTableMetaData.CREATED_DATE, BookTableMetaData.CREATED_DATE);
		sBookProjectionMap.put(BookTableMetaData.MODIFIED_DATE, BookTableMetaData.MODIFIED_DATE);
		
	}
	
         //-- 创建URI最佳匹配器
	private static UriMatcher sUriMatcher = null;
         //-- 注册URI请求类型
	private static final int INCOMMING_BOOK_COLLECTION_URI_INDICATOR = 1;
	private static final int INCOMMING_SINGLE_BOOK_URI_INDICATOR = 2;
	static{
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(TestContentProviderMetaData.AUTHORITY, "books", INCOMMING_BOOK_COLLECTION_URI_INDICATOR);
		sUriMatcher.addURI(TestContentProviderMetaData.AUTHORITY, "books/#", INCOMMING_SINGLE_BOOK_URI_INDICATOR);
	}
	
	
	@Override
	public int delete(Uri uri, String whereClause, String[] whereArgs) {
		Log.i(TAG, "del");
		// TODO Auto-generated method stub
		SQLiteDatabase db = openHelper.getWritableDatabase();
		int count = 0;
		switch(sUriMatcher.match(uri)){
		case INCOMMING_BOOK_COLLECTION_URI_INDICATOR:
			count = db.delete(BookTableMetaData.TABLE_NAME, whereClause, whereArgs);
			break;
		case INCOMMING_SINGLE_BOOK_URI_INDICATOR:
			String rowID = uri.getPathSegments().get(1);
			String where = BookTableMetaData._ID + "=" + rowID + (!TextUtils.isEmpty(whereClause)?" AND (" + whereClause + ')':""); 
			count = db.delete(BookTableMetaData.TABLE_NAME, where, whereArgs);
			break;
			default:
				throw new IllegalArgumentException("Unknown URI " + uri);
		}
		this.getContext().getContentResolver().notifyChange(uri, null);
		
		
		return count;
	}

	@Override
	public String getType(Uri uri) {
		switch(sUriMatcher.match(uri)){
			case INCOMMING_BOOK_COLLECTION_URI_INDICATOR:
				return BookTableMetaData.CONTENT_TYPE;
			case INCOMMING_SINGLE_BOOK_URI_INDICATOR:
				return BookTableMetaData.CONTENT_ITEM_TYPE;
			default:
				throw new IllegalArgumentException("Unknown URI " + uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		Log.i(TAG, "insert");
		
		if(sUriMatcher.match(uri) != INCOMMING_BOOK_COLLECTION_URI_INDICATOR){
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		long now = Long.valueOf(System.currentTimeMillis());
		
		if(values.containsKey(BookTableMetaData.CREATED_DATE) == false){
			values.put(BookTableMetaData.CREATED_DATE, now);
		}
		
		if(values.containsKey(BookTableMetaData.MODIFIED_DATE) == false){
			values.put(BookTableMetaData.MODIFIED_DATE, now);
		}
		
		if(values.containsKey(BookTableMetaData.BOOK_NAME) == false){
			//values.put(BookTableMetaData.BOOK_NAME, "null");
			throw new SQLException("Failed to insert row ,because Book Name is needed " + uri);
		}
		
		if(values.containsKey(BookTableMetaData.BOOK_ISBN) == false){
			values.put(BookTableMetaData.BOOK_ISBN, "Unknown ISBN");
		}
		
		if(values.containsKey(BookTableMetaData.BOOK_AUTHOR) == false){
			values.put(BookTableMetaData.BOOK_AUTHOR, "Unknown author");
		}
		
		SQLiteDatabase db = openHelper.getWritableDatabase();
		long rowID = db.insert(BookTableMetaData.TABLE_NAME, BookTableMetaData.BOOK_NAME, values);
		if(rowID > 0){
			Uri insertBookedUri = ContentUris.withAppendedId(BookTableMetaData.CONTENT_URI, rowID);
			getContext().getContentResolver().notifyChange(insertBookedUri, null);
			return insertBookedUri;
		}
		
		throw new SQLException("Failed to insert row into " + uri);
	}
	

	@Override
	public boolean onCreate() {
		// TODO Auto-generated method stub
		Log.i(TAG, "create table");
		openHelper = new DatabaseHelper(this.getContext());
		Log.i(TAG, openHelper.toString());
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		// TODO Auto-generated method stub
		Log.i(TAG, "query");
		Cursor cursor = null;
		SQLiteQueryBuilder qb = null;
		
		qb = new SQLiteQueryBuilder();
		switch(sUriMatcher.match(uri)){
			case INCOMMING_BOOK_COLLECTION_URI_INDICATOR:
				qb.setTables(BookTableMetaData.TABLE_NAME);
				qb.setProjectionMap(sBookProjectionMap);
				
				break;
			case INCOMMING_SINGLE_BOOK_URI_INDICATOR:
				qb.setTables(BookTableMetaData.TABLE_NAME);
				qb.setProjectionMap(sBookProjectionMap);
				qb.appendWhere(BookTableMetaData._ID + "=" + uri.getPathSegments().get(1));
				break;
			default:
				throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		String orderBy = "";
		if(TextUtils.isEmpty(sortOrder)){
			orderBy = BookTableMetaData.DEFAULT_SORT_ORDER;
		}else{
			orderBy = sortOrder;
		}
		
		SQLiteDatabase db = openHelper.getReadableDatabase();
		Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
		int i = c.getCount();
		ContentResolver cr = this.getContext().getContentResolver();
		c.setNotificationUri(cr, uri);
		
		return c;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		Log.i(TAG, "update");
		SQLiteDatabase db = openHelper.getWritableDatabase();
		int count = 0;
		switch(sUriMatcher.match(uri)){
		case INCOMMING_BOOK_COLLECTION_URI_INDICATOR:
			count = db.update(BookTableMetaData.TABLE_NAME, values, selection, selectionArgs);
			
			break;
		case INCOMMING_SINGLE_BOOK_URI_INDICATOR:
			String rowID = uri.getPathSegments().get(1);
			String where = "BookTableMetaData._ID" + "=" + rowID + (!TextUtils.isEmpty(selection)?" AND(" + selection + ')':"");
			count = db.update(BookTableMetaData.TABLE_NAME, values, where, selectionArgs);
			
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		getContext().getContentResolver().notifyChange(uri, null);
		
		return count;
	}
	
		
	//-- create table
	public class DatabaseHelper extends SQLiteOpenHelper{

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

		@Override
		public void onCreate(SQLiteDatabase db) {
			// TODO Auto-generated method stub
			String sql = "CREATE TABLE " + BookTableMetaData.TABLE_NAME
						+ " (" + TestContentProviderMetaData.BookTableMetaData._ID 
						+ " INTEGER PRIMARY KEY,"
						+ BookTableMetaData.BOOK_NAME + " TEXT,"
						+ BookTableMetaData.BOOK_ISBN + " TEXT,"
						+ BookTableMetaData.BOOK_AUTHOR + " TEXT,"
						+ BookTableMetaData.CREATED_DATE + " INTEGER,"
						+ BookTableMetaData.MODIFIED_DATE + " INTEGER"
						+ ");";
			Log.i(TAG, db.getPath());
			db.execSQL(sql);
			
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			// TODO Auto-generated method stub
			Log.i(TAG, "Upgrade database from " + oldVersion + " to "
					+ newVersion + ", which will destroy old data!");
			
			String sql = "DROP TABLE IF EXISTS " + BookTableMetaData.TABLE_NAME;
			db.execSQL(sql);
			onCreate(db);
		}
		
	}
}



class TestContentProviderMetaData {
	public static final String DATABASE_NAME = "books.db";
	public static final int DATABASE_VERSION = 1;
	
	public static final String AUTHORITY = "tl.android.provider.bookprovider";
	
	public static final String BOOKS_TABLE_NAME = "books";
	
	public static final class BookTableMetaData implements BaseColumns{
		public static final String TABLE_NAME = "books";
		
		// String 
		public static final String BOOK_NAME = "name";
		// String
		public static final String BOOK_ISBN = "isbn";
		// String
		public static final String BOOK_AUTHOR = "author";
		// Integer
		public static final String CREATED_DATE = "created";
		// Integer
		public static final String MODIFIED_DATE = "modified";
		
		public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/books");
		//-- 多记录
		public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.androidbook.book";
		//-- 单记录
		public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.androidbook.book";
		
		public static final String DEFAULT_SORT_ORDER = "modified DESC"; 
		
		
	}
	
	
}






MainActivity.java
package tl.android.apps;

import tl.android.data.TestContentProvider;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;

public class MainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        ContentResolver cr = this.getContentResolver();
        ContentValues cv = new ContentValues();
        cv.put("name", "android pro");
        cr.insert(TestContentProvider.CONTENT_URI, cv);
        cv.put("name", "android programming");
        cr.insert(TestContentProvider.CONTENT_URI, cv);
       
    }
}




AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="tl.android.apps" android:versionCode="1" android:versionName="1.0">
	<application android:icon="@drawable/icon" android:label="@string/app_name">
		<activity android:name="tl.android.apps.MainActivity" android:label="@string/app_name">
			<intent-filter>
				<action android:name="android.intent.action.MAIN" />
				<category android:name="android.intent.category.LAUNCHER" />
			</intent-filter>
		</activity>

		<provider android:authorities="tl.android.provider.bookprovider"
			android:name="tl.android.data.TestContentProvider"></provider>
	</application>

	<uses-sdk android:minSdkVersion="4" />


</manifest> 












分享到:
评论
1 楼 woyaowenzi 2012-05-27  
试一试。有问题再向你请教。

相关推荐

    Android实现使用自定义ContentProvider共享生词本数据库

    Android高级编程雪梨作业之自定义ContentProvider 将任务01生词本作业中生成的生词本数据库通过自定义ContentProvider的方式,共享给其他应用。 要求如下: (1) 使用自定义SQLiteOpenHelper来管理数据库; (2) 提交...

    Android 之 自定义ContentProvider的使用

    要创建自定义ContentProvider,首先需要创建一个新的Java类,继承自`android.content.ContentProvider`。在这个类中,需要重写以下几个关键方法: - `onCreate()`: 初始化方法,通常用于创建SQLite数据库或进行...

    android 自定义 ContentProvider 以及 ContentResolver

    总之,自定义ContentProvider和使用ContentResolver是Android平台中实现跨应用数据共享的重要手段,理解并熟练掌握这两者对于提升Android应用的可扩展性和可维护性至关重要。在实际项目中,根据需求合理设计和实现...

    android自定义contentprovider

    总结,自定义ContentProvider是Android应用之间数据共享的重要手段。通过理解其工作原理,我们可以构建自己的数据访问接口,同时灵活地读取系统资源如联系人、彩信和通话记录。在实际开发中,结合ContentResolver,...

    Android 自定义ContentProvider简单实例

    "Android 自定义ContentProvider简单实例" Android 自定义ContentProvider简单实例主要介绍了Android 自定义ContentProvider简单实例的相关资料,需要的朋友可以参考下。Android 允许我们定义自己的ContentProvider...

    Android学习之自定义ContentProvider类

    这是学习ContentProvider的第二个练习。 里面自定义ContentProvider类来与SQLite交互。 大致类容就是:通过ContentProvider,创建自己的.db,操作自己的.db. 代码里有详细的解释

    android 数据库 以及自定义ContentProvider demo

    本示例“android 数据库 以及自定义ContentProvider demo”将带你深入理解这两个概念,并通过实践操作演示如何在Android项目中实现它们。 首先,我们来了解Android数据库。Android系统使用SQLite作为默认的轻量级...

    自定义ContentProvider的简单例子

    需要指定`android:name`为自定义ContentProvider类的全名,`android:authorities`是ContentProvider的唯一标识,通常是一个应用的包名加上自定义的标识。 例如: ```xml android:name=".MyContentProvider" ...

    自定义contentprovider

    自定义ContentProvider是开发者根据需求创建的,用于暴露自己应用中的数据,让其他应用可以安全地读取或写入这些数据。本篇文章将深入讲解如何创建并使用自定义ContentProvider。 一、ContentProvider概述 ...

    关于自定义ContentProvider的Demo

    首先,我们来看“自定义ContentProvider”。ContentProvider是Android四大组件之一,它的主要职责是为其他应用提供数据访问接口。自定义ContentProvider通常涉及以下步骤: 1. **创建ContentProvider类**:你需要...

    android 用ContentProvider操作文件

    3. 注册ContentProvider:在AndroidManifest.xml文件中注册ContentProvider,设置对应的`&lt;provider&gt;`标签,指定`android:name`(自定义ContentProvider类名)、`android:authorities`(唯一标识符)等属性。...

    自定义ContentProvider

    综上所述,自定义ContentProvider是Android开发中非常重要的一个部分,它使得数据能够在不同应用间无缝流动。理解并熟练掌握ContentProvider的创建和使用,对于提升应用的扩展性和交互性具有重要意义。

    ContentProvider自定义以及使用系统ContentProvider

    本篇文章将深入探讨如何自定义ContentProvider以及如何使用系统提供的ContentProvider。 首先,理解ContentProvider的基本概念至关重要。ContentProvider是Android系统中的一种机制,它封装了对数据的操作,如读取...

    自定义ContentProvider完成数据交互

    本篇文章将深入探讨如何自定义ContentProvider来实现数据交互。 首先,我们需要了解ContentProvider的基本结构。一个自定义的ContentProvider需要继承自`android.content.ContentProvider`类,并重写其中的关键方法...

Global site tag (gtag.js) - Google Analytics