`
xmong
  • 浏览: 258625 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

android数据存储之ContentProvider

阅读更多
android数据存储之ContentProvider

在android中应用的数据一般都是私有的,如果两个应用之间要共享数据,可以通过Content provider来实现。即是,如果一个应用实现了ContentProvider接口,就可以将自己的数据暴露出去,其他应用就可以通过ContentResolver来获取ContentProvider提供的接口服务,只是这种数据访问是通过RUI来表示的,这样就实现应用之间的数据共享。
在android中提供两类数据共享,一类是系统应用的数据共享,即系统应用已经实现了ContentProvider接口,只需要在其他应用中调用ContentResolver就可以访问。另一类是自定义数据共享,需要自己去实现ContentProvider接口。
(1)ContentProvider(android.content.ContentProvider),实现这个接口可以将应用的数据服务分布出去供其他应用访问。ContentProvider为存储和获取数据提供统一的接口。实现这个接口需要实现下面几个方法。
public Uri insert(Uri uri, ContentValues values);//插入数据
	
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder);//查去数据
	
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs); //更新数据
	
	public int delete(Uri uri, String selection, String[] selectionArgs) ; //删除数据

	public String getType(Uri uri); //获取数据的mime类型 

	public boolean onCreate(); //创建ContentProvider时回调该方法

ContentProvider中对数据操作的方法都有一个android.net.Uri类型的参数,该参数代表操作数据的唯一标识。
content://com.example.MyDatabase/users/#
URI由三部分组成格式为:scheme+authority+path,scheme是content://表示移动的协议标识。authority用于唯一标识这个ContentProvider,一般以类的全名命名。path是/user/#可以用来表示我们要操作的数据。
Android提供了两个工具类来对Uri进行操作:UriMatcher的Uri进行注册和匹配,ContentUris对Uri进行组装。
基于前面sqlite的列子我们可以通过实现下面的列子来叙述android中ContentProvider的创建和使用。
设计如下:
MyDatabase:数据库结构类,是一个常量类存储数据库结构信息。
MysqliteDatabase:sqlite数据库操作类,通过该类构建获取SQLiteDatabase对象操作数据库。
MyContentProvider:继承ContentProvider类,实现ContentProvider类的方法。
Activity4:Activity类。

MyDatabase实现如下:
package com.contentProvider;

import android.net.Uri;
import android.provider.BaseColumns;

/**
 * 常量类表示数据库表结构
 * @author xmong
 */
public class MyDatabase {
	
	//数据库名
	public final static String DB_NAME = "db_test";
	//数据库版本
	public final static int DB_VERSION = 1;
	//
	public final static String AUTHORITY = "com.contentProvider.MyDatabase";
	
	/**
	 * User表结构,
	 * 实现BaseColumns常量接口,包含两个默认属性_ID和_COUNT
	 */
	public static class User implements BaseColumns{
		public final static String TAB_NAME = "user"; //表名
		public final static String COL_NAME = "name"; //用户名
		//访问该ContentProvider的URI
		public static final Uri CONTENT_URI = Uri.parse("content://"+AUTHORITY+"/users");
		//该ContentProvider所返回的数据类型
		public static final String CONTENT_TYPE_DIR = "vnd.android.cursor.dir/vnd.mydatabase.user";
		public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/vnd.mydatabase.user";
		//该ContentProvider的RUI匹配类型
		public static final int URI_TYPE_DIR = 1;
		public static final int URI_TYPE_ITEM = 2;
	}

MySqliteDatabase实现如下:
package com.contentProvider;


import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * @author xmong
 */
public class MySqliteDatabase{
	
	//sqlite数据库对象
	private SQLiteDatabase sqliteDatabase = null; 

	/**
	 * 数据库帮助类,继承SQLiteOpenHelper
	 */
	static class DatabaseHelper extends SQLiteOpenHelper{
		
		/**
		 * 构造数据库对象
		 * @param context context对象
		 * @param name 数据库名
		 * @param factory 可选游标工厂,通常可是null
		 * @param version 当前数据库版本
		 */
		public DatabaseHelper(Context context, String name,
				CursorFactory factory, int version) {
			super(context, name, factory, version);
		}

		//根据context构建数据库帮助对象
		public DatabaseHelper(Context context) {
			//调用自身构造方法
			this(context, MyDatabase.DB_NAME, null,  MyDatabase.DB_VERSION);
		}

		/**
		 * 该函数是在第一次创建数据库的时候执行,即第一次调用SQLiteOpenHelper对象的
		 * getWritableDatabase()或getReadableDatabase()方法时才执行该方法
		 * 可用于执行数据库初始化工作
		 */
		@Override
		public void onCreate(SQLiteDatabase db) {
			
			System.out.println("create table:"+ MyDatabase.User.TAB_NAME);
			//创建表sql语句
			String sql = "create table "+MyDatabase.User.TAB_NAME
					+" ("+MyDatabase.User._ID+" integer primary key autoincrement,"
					+MyDatabase.User.COL_NAME+" varchar(20))";
			//执行sql语句
			db.execSQL(sql);
		}

		/**
		 * 第一个参数是SQLiteDatabase对象,第二个参数是旧的数据库版本,第三个参数是新的数据库版本号,
		 * 可用于执行数据库的升级,将一个数据库从旧版本转变到新版本执行相应的操作
		 */
		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			//可执行一些升级或修改数据库操作
			System.out.println("update database");
		}
		
	}
	
	/**
	 * 根据context构建sqlite数据库对象
	 * @param context
	 */
	public MySqliteDatabase(Context context) {
		/**
		 * 通过调用数据库帮助对象SQLiteOpenHelper的getWritableDatabase()方法
		 * 获取一个可读写的数据库对象sqliteDatabase
		 */
		sqliteDatabase = (new DatabaseHelper(context)).getWritableDatabase();
	}
	
	
	/**
	 * 关闭数据库,数据库操作完后需要释放资源
	 */
	public void close() {
		sqliteDatabase.close();
	}
	
	/**
	 * 获取sqliteDatabase对象
	 * @return
	 */
	public SQLiteDatabase getSqliteDatabase(){
		return sqliteDatabase;
	}
}

}

MyContentProvider实现如下:

package com.contentProvider;

import java.util.HashMap;
import java.util.Map;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;

public class MyContentProvider extends ContentProvider{

	private SQLiteDatabase sqLiteDatabase; //sqlite数据库对象
	private static UriMatcher uriMatcher;
	private static Map<String, String> userProjectionMap;
	static {
		//注册需要匹配的uri,将uri与匹配码相匹配
		uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		//注册调用match()方法时,匹配content://com.contentProvider.MyDatabase/user路径,则返回匹配码1
		uriMatcher.addURI(MyDatabase.AUTHORITY, "users", MyDatabase.User.URI_TYPE_DIR);
		uriMatcher.addURI(MyDatabase.AUTHORITY, "users/#", MyDatabase.User.URI_TYPE_ITEM);
		
		userProjectionMap = new HashMap<String, String>();
		userProjectionMap.put(MyDatabase.User._ID, MyDatabase.User._ID);
		userProjectionMap.put(MyDatabase.User.COL_NAME, MyDatabase.User.COL_NAME);
	}
	
	//根据传入的URI,返回该URI所表示的数据MIME类型
	@Override
	public String getType(Uri uri) {
		System.out.println("contentProvider getType");
		switch(uriMatcher.match(uri)){
		case MyDatabase.User.URI_TYPE_DIR:
			return MyDatabase.User.CONTENT_TYPE_DIR;
		case MyDatabase.User.URI_TYPE_ITEM:
			return MyDatabase.User.CONTENT_TYPE_ITEM; 
		default:
			throw new IllegalArgumentException("Unknown URI:" + uri);
		}
	}

	//插入数据
	@Override
	public Uri insert(Uri uri, ContentValues values) {
		System.out.println("contentProvider intert");
		Uri insertUri = null;
		long id = sqLiteDatabase.insert(MyDatabase.User.TAB_NAME, null, values);
		if(id>0){
			//生成uri:content://com.contentProvider.MyDatabase/user/id
			insertUri = ContentUris.withAppendedId(MyDatabase.User.CONTENT_URI, id);
			//通知监听器,数据已经改变
			getContext().getContentResolver().notifyChange(insertUri, null);
			return insertUri;
		}
		return insertUri;
	}

	//查去数据
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		System.out.println("contentProvider query");
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		/**
		 * 调用UriMatcher匹配uri类型,返回匹配码
		 * 根据不同的uri类型构建不同的sqlQuery
		 */
		switch (uriMatcher.match(uri)) {
		case MyDatabase.User.URI_TYPE_DIR:
			qb.setTables(MyDatabase.User.TAB_NAME);
			qb.setProjectionMap(userProjectionMap);
			break;
		case MyDatabase.User.URI_TYPE_ITEM:
			qb.setTables(MyDatabase.User.TAB_NAME);
			qb.setProjectionMap(userProjectionMap);
			qb.appendWhere(MyDatabase.User._ID+"="+uri.getPathSegments().get(1));
			break;
		default:
			throw new IllegalArgumentException("Unknown URI:" + uri);
		}
		//设置order by参数
		Cursor cursor = qb.query(sqLiteDatabase, projection, selection, 
				selectionArgs, null, null, null);
		return cursor;
	}
	
	//修改数据
	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		System.out.println("contentProvider update");
		switch (uriMatcher.match(uri)) {
		case MyDatabase.User.URI_TYPE_DIR:
			return sqLiteDatabase.update(MyDatabase.User.TAB_NAME, values, selection, selectionArgs);
		case MyDatabase.User.URI_TYPE_ITEM:
			String uid = uri.getPathSegments().get(1);
			return sqLiteDatabase.update(MyDatabase.User.TAB_NAME, values,
					MyDatabase.User._ID+"="+uid
					+(!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
		default:
			throw new IllegalArgumentException("Unknown URI:" + uri);
		}
	}
	
	//删除数据
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		System.out.println("contentProvider delete");
		switch (uriMatcher.match(uri)) {
		case MyDatabase.User.URI_TYPE_DIR:
			return sqLiteDatabase.delete(MyDatabase.User.TAB_NAME, selection, selectionArgs);
		case MyDatabase.User.URI_TYPE_ITEM:
			String uid = uri.getPathSegments().get(1);
			return sqLiteDatabase.delete(MyDatabase.User.TAB_NAME,
					MyDatabase.User._ID+"="+uid
					+(!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);
		default:
			throw new IllegalArgumentException("Unknown URI:" + uri);
		}
	}

	//该方法在ContentProvider创建时被执行
	@Override
	public boolean onCreate() {
		System.out.println("contentProvider create");
		//获取sqLiteDatabase对象
		sqLiteDatabase = (new MySqliteDatabase(getContext())).getSqliteDatabase();
		return false;
	}
	
	
	
}

Activity4实现如下:
package com.contentProvider;

import com.example.R;

import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;

public class Activity4 extends Activity {

	private EditText editText; //输入框
	private Button insertBtn; //插入按钮
	private Button queryBtn; //查询按钮
	private Button updateBtn; //更新按钮
	private Button deleteBtn; //删除按钮
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity3);
		//从视图中获取控件对象
		editText = (EditText)findViewById(R.id.text);
		insertBtn = (Button)findViewById(R.id.insert);
		queryBtn = (Button)findViewById(R.id.query);
		updateBtn = (Button)findViewById(R.id.update);
		deleteBtn = (Button)findViewById(R.id.delete);
		//为按钮对象设置点击事件
		insertBtn.setOnClickListener(insertBtnClick);
		queryBtn.setOnClickListener(queryBtnClick);
		updateBtn.setOnClickListener(updateBtnClick);
		deleteBtn.setOnClickListener(deleteBtnClick);
		
	}
	
	//插入按钮点击事件监听器
	OnClickListener insertBtnClick = new OnClickListener() {
			
		@Override
		public void onClick(View v) {
			String text = editText.getText().toString().trim();
			ContentValues cv = new ContentValues();
			cv.put(MyDatabase.User.COL_NAME, text);
			Uri uri = getContentResolver().insert(MyDatabase.User.CONTENT_URI, cv);
			System.out.println(uri.toString());
		}
	};
	
	//查取按钮点击事件监听器
	OnClickListener queryBtnClick = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			//根据输入框中是否输入id号来构建content的uri
			String text = editText.getText().toString().trim();
			String uidUri = TextUtils.isEmpty(text)? "":"/"+text;
			Uri uri = Uri.parse(MyDatabase.User.CONTENT_URI+uidUri);
			Cursor cursor = getContentResolver().query(uri, 
					new String[]{MyDatabase.User._ID, MyDatabase.User.COL_NAME}, null, null, null);
			//遍历游标输出查取的数据
			for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()){
				String str = MyDatabase.User._ID+":"+cursor.getInt(cursor.getColumnIndex(MyDatabase.User._ID))
						+","+MyDatabase.User.COL_NAME+":"+cursor.getString(cursor.getColumnIndex(MyDatabase.User.COL_NAME));
				System.out.println(str);
			}
		}
	};
	
	//修改按钮点击事件监听器
	OnClickListener updateBtnClick = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			String text = editText.getText().toString().trim();
			String[] arr = text.split(",");
			ContentValues cv = new ContentValues();
			cv.put(MyDatabase.User.COL_NAME, arr[1]);
			String uidUri = TextUtils.isEmpty(arr[0])? "":"/"+arr[0];
			Uri uri = Uri.parse(MyDatabase.User.CONTENT_URI+uidUri);
			getContentResolver().update(uri, cv, null, null);
		}
	};
	
	//删除按钮点击事件监听器
	OnClickListener deleteBtnClick = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			String text = editText.getText().toString().trim();
			String uidUri = TextUtils.isEmpty(text)? "":"/"+text;
			Uri uri = Uri.parse(MyDatabase.User.CONTENT_URI+uidUri);
			getContentResolver().delete(uri, null, null);
		}
	};
	
	//按键事件
	public boolean onKeyUp(int keyCode, KeyEvent event) {
		//当按键为回退键是结束这个activity
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			Activity4.this.finish();
		}
		return true;
	};
}


修改AndroidManifest.xml文件,分布ContentProvider服务。
<provider  android:name="com.contentProvider.MyContentProvider"
            android:authorities="com.contentProvider.MyDatabase"></provider>

上面的配置是name属性是指向自定义ContentProvider类,authorities属性是配置该ContentProvider uri的authority。

运行程序:
后台输出:
contentProvider create
在输入框中输入“xmong”,点击insert按钮,后台输出:
contentProvider insert
content://com.contentProvider.MyDatabase/users/1
清空输入框,点击query按钮,后台输出:
contentProvider query
_id:1,name:xmong
……
从操作结果我们可以知道ContentProvider的分布成功,调用也成功。

源代码下载:http://xmong.iteye.com/blog/1852204
分享到:
评论

相关推荐

    Android开发教程之ContentProvider数据存储

    主要介绍了Android开发教程之ContentProvider数据存储的相关资料,需要的朋友可以参考下

    关于android的数据存储-SQLite-ContentProvider-preferences

    关于android的数据存储-SQLite-ContentProvider-preferences

    Android数据存储和访问实验报告

    2.掌握各种文件存储的区别与适用情况; 3.了解SQLite数据库的特点和体系结构; 4.掌握SQLite数据库的建立和操作方法; 5.理解ContentProvider的用途和原理; 6.掌握ContentProvider的创建与使用方法。 源码和整个...

    android数据存储与访问

    数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的4种方式,分别是:1 使用SharedPreferences存储数据;2 文件存储数据;3 SQLite数据库存储数据;4 使用ContentProvider存储数据;

    基于Android ContentProvider的总结详解

    1.适用场景1) ContentProvider为存储和读取数据提供了...虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferen

    APP开发教程 Java Android移动端开发 13、Android数据存储和共享(二) 共25页.pptx

    Android数据共享概述 ContentProvider注册/实现 UriMatcher/ContentUris 系统ContentProvider 联系人 系统设置…

    Android开发之ContentProvider的使用详解

     Content Provider为存储数据和获取数据提供了统一的接口,它可以完成在不同应用程序下的数据共享,而在上一篇文章Android开发之SQLite的使用方法讲到的SQLite只能在同一个程序中共享数据。另外android为一些常见的...

    ContentProvider简介

    总结ContentProvider知识,让大家更好的去学习android知识!数据库数据存储!

    Android数据基本存储

    Android数据基本存储方式 SharedPreference SQL基本语句 SharedPreference SQLite 文件 内容提供者ContentProvider 网络存储

    Android 实例分析ContentProvider详解

    ContentProvider是android的四大组件之一,同时与SharedPreferences、IO、SQLite、网络共同构成了五种android存储技术。是android定义的一个管理访问结构化数据机制。android支持的Sqlite是不支持跨进程、跨应用访问...

    Android 数据存储与数据共享PPT

    (1)熟悉Android系统提供的四种数据存储方式:SharePreference、SQLite、ContentProvider和File (2)学会编写程序使用SQLite数据库存储数据 (3)学会编写程序使用SharedPreference对象存储数据 (4)学会编写...

    eoeAndroid特刊第八期:Android数据存储方式 pdf

    eoeAndroid特刊第八期:Android数据存储方式 pdf  在Android中,可供选择的存储方式有SharedPreferences、文件存储、SQLite数据库方式、内容提供器(content provider)和网络,本章将详细介绍这些知识:  • ...

    android 数据存储技术 详解

    android 数据存储技术 详解,会对大家有帮助的。里面包含了SharedPreference,文件存储,SQLITE,ContentProvider 的相应的源码例子。

    Android 中ContentProvider的实例详解

    * Android中的Content Provider 机制可支持在多个应用中存储和读取数据。这也是跨应用   共享数据的唯一方式。在Android系统中,没有一个公共的内存区域,供多个应用共享存储数据; * Android 提供了一些主要...

    Android实现数据存储技术

    本文介绍Android中的5种数据存储方式。 数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用SharedPreferences存储数据; 2 文件存储数据; 3 SQLite数据库...

    contentprovider

    当应用继承ContentProvider类 并重写该类用于提供数据和存储数据的方法 就可以向其他应用共享其数据 虽然使用其他方法也可以对外共享数据 但数据访问方式会因数据存储的方式而不同 如:采用文件方式对外共享数据 ...

    android数据存储

    详细的介绍了android数据存储的几种方式:xml存储,io数据存储,文件系统,sdcard访问(详细的步骤),sqlite访问(详细的步骤以及相关的sqlite知识点),ContentProvider,很有参考价值!!!

    android ContentProvider

    android ContentProvider 不用应用程序的数据共享,数据的存储方式

    android数据存储培训资料

    资料大纲 掌握Android在存储方面的系统知识 掌握SharedPreferences存储应用 掌握SQLite方式的存储与应用 掌握ContentProvider方式的存储

Global site tag (gtag.js) - Google Analytics