android学习之contentProvider

翻译 2015年11月19日 16:41:49

一、相关ContentProvider概念解析:

1、ContentProvider简介
在Android官方指出的Android的数据存储方式总共有五种,分别是:Shared Preferences、网络存储、文件存储、外储存储、SQLite。但是我们知道一般这些存储都只是在单独的一个应用程序之中达到一个数据的共享,有时候我们需要操作其他应用程序的一些数据,例如我们需要操作系统里的媒体库、通讯录等,这时我们就可能通过ContentProvider来满足我们的需求了。

2、为什么要选择ContentProvider?

ContentProvider向我们提供了我们在应用程序之前共享数据的一种机制,而我们知道每一个应用程序都是运行在不同的应用程序的,数据和文件在不同应用程序之间达到数据的共享不是没有可能,而是显得比较复杂,而正好Android中的ContentProvider则达到了这一需求,比如有时候我们需要操作手机里的联系人,手机里的多媒体等一些信息,我们都可以用到这个ContentProvider来达到我们所需。

1)、ContentProvider为存储和获取数据提供了统一的接口。ContentProvide对数据进行封装,不用关心数据存储的细节。使用表的形式来组织数据。
2)、使用ContentProvider可以在不同的应用程序之间共享数据。 
3)、Android为常见的一些数据提供了默认的ContentProvider(包括音频、视频、图片和通讯录等)。 
总的来说使用ContentProvider对外共享数据的好处是统一了数据的访问方式。

3、Uri介绍

为系统的每一个资源给其一个名字,比方说通话记录。
1)、每一个ContentProvider都拥有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。 
2)、Android所提供的ContentProvider都存放在android.provider包中。 将其分为A,B,C,D 4个部分:

\
A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;"content://"
B:URI 的标识,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。它定义了是哪个Content Provider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在 元素的 authorities属性中说明:一般是定义该ContentProvider的包.类的名称
C:路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了;"content://com.bing.provider.myprovider/tablename"
D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; "content://com.bing.provider.myprovider/tablename/#" #表示数据id。

PS:

路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
1、要操作person表中id为10的记录,可以构建这样的路径:/person/10
2、要操作person表中id为10的记录的name字段, person/10/name
3、要操作person表中的所有记录,可以构建这样的路径:/person
4、要操作xxx表中的记录,可以构建这样的路径:/xxx
5、当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:
要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
6、如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:Uri uri = Uri.parse("content://com.bing.provider.personprovider/person")

4、UriMatcher类使用介绍

因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris 。掌握它们的使用,会便于我们的开发工作。

5。 ContentProvider:为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。Android已经为常见的一些数据提供了默认的ContentProvider
  1、ContentProvider使用表的形式来组织数据
   无论数据的来源是什么,ContentProvider都会认为是一种表,然后把数据组织成表格
  2、ContentProvider提供的方法
   query:查询
   insert:插入
   update:更新
   delete:删除
   getType:得到数据类型
   onCreate:创建数据时调用的回调函数
  3、每个ContentProvider都有一个公共的URI,这个URI用于表示这个ContentProvider所提供的数据。Android所提供的ContentProvider都存放在android.provider包当中
 6、ContentProvider的内部原理
  自定义一个ContentProvider,来实现内部原理
  步骤:
  1、定义一个CONTENT_URI常量(里面的字符串必须是唯一)
  Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentprovider");
  如果有子表,URI为:
  Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentProvider/users");
  2、定义一个类,继承ContentProvider
  Public class MyContentProvider extends ContentProvider
  3、实现ContentProvider的所有方法(query、insert、update、delete、getType、onCreate)

这里上传自己写的contentProvider类

数据源Bean

package com.leige.stu.domain;

public class Student {
	private int id;
	private String name;
	private String sex;
	private int age;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public Student(int id, String name, String sex, int age) {
		super();
		this.id = id;
		this.name = name;
		this.sex = sex;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", sex=" + sex
				+ ", age=" + age + "]";
	}
	public Student() {
		super();
	}
	
	
}

ContentProvider类,详细解释都在类的注解中

欢迎大家纠错

package com.leige.stu.mycontentprovider;

import com.leige.stu.mysqllite.StudentSqlHelper;
import com.leige.stu.mysqllite.Studentdao;

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.net.Uri;

public class MyProvider extends ContentProvider {
	private StudentSqlHelper helper;
	private static final UriMatcher uriMatcher;
	//定义authority
	private static final String authority="com.leige.stu.mycontentprovider.MyProvider";
	//定义匹配操作码
	private static final int STUDENT_INSERT_CODE = 0;
	private static final int STUDENT_UPDATE_CODE = 1;
	private static final int STUDENT_FINDBYID_CODE = 2;
	private static final int STUDENT_DELETE_CODE = 3;
	private static final int STUDENT_FINDALL_CODE = 4;
	static{
		//实例化UriMatcher
		uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
		//匹配路径content://com.leige.stu.mycontentprovider.MyProvider/student/insert
		uriMatcher.addURI(authority, "student/insert", STUDENT_INSERT_CODE);
		//匹配路径content://com.leige.stu.mycontentprovider.MyProvider/student/delete
		uriMatcher.addURI(authority, "student/delete", STUDENT_DELETE_CODE);
		//匹配路径content://com.leige.stu.mycontentprovider.MyProvider/student/update
		uriMatcher.addURI(authority, "student/update", STUDENT_UPDATE_CODE);
		//匹配路径content://com.leige.stu.mycontentprovider.MyProvider/student/findById/#
		uriMatcher.addURI(authority, "student/findById/#", STUDENT_FINDBYID_CODE);
		//匹配路径content://com.leige.stu.mycontentprovider.MyProvider/student/findAll
		uriMatcher.addURI(authority, "student/findAll", STUDENT_FINDALL_CODE);
	}
	@Override
	public boolean onCreate() {
		// TODO Auto-generated method stub
		//创建数据库
	
		helper=new StudentSqlHelper(getContext(), "stu.db",null , 1);
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		// TODO Auto-generated method stub
		//得到数据库
		SQLiteDatabase db=helper.getReadableDatabase();
			switch (uriMatcher.match(uri)) {
			case STUDENT_FINDALL_CODE:
			{
				if(db.isOpen()){
				//查询得到游标对象,返回,查询所有
				Cursor cursor=db.query( "student", projection, selection,
						selectionArgs, null, null,sortOrder);
				return cursor;
				}
			}
				break;
			case STUDENT_FINDBYID_CODE:
			{
				if(db.isOpen()){//查询单个,
					int id=(int) ContentUris.parseId(uri);
					Cursor cursor=db.query("student",projection ,"_id=", 
							new String[]{1+""}, null, null, sortOrder);
					return cursor;
					
				}
			}
			break;
			default:
				break;
			}
			//返回游标,不能关闭db,切记
			//db.close();
		return null;
	}

	@Override
	public String getType(Uri uri) {
		// TODO Auto-generated method stub
		switch (uriMatcher.match(uri)) {
		case STUDENT_FINDALL_CODE:
			return "vnd.android.cursor.dir/student";
		case STUDENT_FINDBYID_CODE:
			return "vnd.android.cursor.item/student";
		default:
			break;	
		}
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		SQLiteDatabase db=helper.getWritableDatabase();
		switch (uriMatcher.match(uri)) {
		case STUDENT_INSERT_CODE:
		{
			if(db.isOpen()){
				long id=db.insert("student",null, values);
				db.close();
				return ContentUris.withAppendedId(uri, id);
			}
		}
			break;

		default:
			break;
		}
		return null;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		
		// TODO Auto-generated method stub
		SQLiteDatabase db=helper.getWritableDatabase();
		switch (uriMatcher.match(uri)) {
		case STUDENT_DELETE_CODE:
		{
			if(db.isOpen()){
				int count=db.delete("student",  selection, selectionArgs);
				db.close();
				return count;
				
			}
		}
			break;

		default:
			break;
		}
		return 0;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		SQLiteDatabase db=helper.getWritableDatabase();
		switch (uriMatcher.match(uri)) {
		case STUDENT_UPDATE_CODE:
		{
			if(db.isOpen()){
				int count=db.update("student", values, selection, selectionArgs);
				db.close();
				return count;
				
			}
		}
			break;

		default:
			break;
		}
		return 0;
	}

}

contentProvider类写完后,需要发布到机器上,提供统一的uri接口可以被外部程序所访问,另外contentProvider是android的四大组件之一,所以需要在androidMainfest.xml文件中注册

例如

     <provider android:name=".mycontentprovider.MyProvider"
             android:authorities="com.leige.stu.mycontentprovider.MyProvider"
             android:readPermission="myprovider.read"
            android:writePermission="myprovider.write"
            >
   <!--
   自定义权限需要声明,才会被系统所认可,所以需要定义permission节点,声明自定义权限        
    android:readPermission="myprovider.read"
            android:writePermission="myprovider.write" -->         
        </provider>
这里定义了对contentprovider的读写权限设置,如果在其他程序中访问contentprovider,需要申请权限

测试类代码

package comleige.testcontentprovider.test;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log;

public class MyTest extends AndroidTestCase {
	public void test(){
		//得到内容提供者的访问对象
		ContentResolver resolver = getContext().getContentResolver();
		//设定uri
		Uri uri=Uri.parse("content://com.leige.stu.mycontentprovider.MyProvider/student/insert");
		ContentValues values=new ContentValues();
		values.put("name", "磊哥2");
		values.put("sex", "男");
		values.put("age", 18);
		resolver.insert(uri, values);
	}

/*	public void testFindById(){
		ContentResolver resolver=getContext().getContentResolver();
		Uri uri=Uri.parse
	("content://com.leige.stu.mycontentprovider.MyProvider/student/findById/#");
		uri=ContentUris.withAppendedId(uri,1);
		Cursor cursor=resolver.query(uri,
				new String[]{"_id","name","sex","age"}, null, null, null);
		if(cursor!=null){
			cursor.moveToFirst();
			int id=cursor.getInt(0);
			String name=cursor.getString(1);
			String sex=cursor.getString(2);
			int age=cursor.getInt(3);
			Student s=new Student(id,name,sex,age);
			System.out.println(s);
			Log.i("err", s.toString());
			Log.d("err", "leige");
		}
	}*/
}



Android数据存储-ContentProvider总结

使用ContentProvider存储数据 1   简介 ContentProvider是android数据存储实现方式之一,它向应用程序之间的数据共享提供了一种机制,它会把数据以表格数据组织的方式对...
  • qq282330332
  • qq282330332
  • 2016年02月19日 15:45
  • 761

Android应用实例之----基于Service与ContentProvider的音乐播放实例!

原文在这里: 大家好今天我将为大家分享基于Service与ContentProvider的音乐播放实例,对于接触Android有一些时日的人来说,Android的核心也就是Activity,Se...
  • goldenfish1919
  • goldenfish1919
  • 2014年10月21日 18:56
  • 1325

Android应用安全之Content Provider安全

android平台提供了Content Provider,将一个应用程序的指定数据集提供给其它应用程序。这些数据可以存储在文件系统、SQLite数据库中,或以任何其它合理的方式存储。其他应用可以通过C...
  • omnispace
  • omnispace
  • 2016年03月07日 15:32
  • 985

Android 进阶11:进程通信之 ContentProvider 内容提供者

学习启舰大神,每篇文章写一句励志的话,与大家共勉。When you are content to be simply yourself and don’t compare or compete, ev...
  • u011240877
  • u011240877
  • 2017年06月02日 23:24
  • 3087

Android安全开发之Provider组件安全

如果在AndroidManifest文件中将某个Content Provider的exported属性设置为true,则多了一个攻击该APP的攻击点。如果此Content Provider的实现有问题...
  • AliMobileSecurity
  • AliMobileSecurity
  • 2016年06月02日 11:19
  • 4822

四大组件之ContentProvider(一)-使用系统提供的ContentProvider

什么是ContentProvider?它有什么作用?如何使用?本文将细致的介绍ContentProvider功能和使用相关的初步知识。...
  • anddlecn
  • anddlecn
  • 2016年06月16日 13:27
  • 9201

Android之通过ContentProvider共享文件

使用ContentProvider共享文件时,一定要重写openFile方法,否则会报异常。 如: public class ContentProviderDemo extends Content...
  • zhangyongfeiyong
  • zhangyongfeiyong
  • 2016年07月08日 11:09
  • 743

Android ContentProvider query参数

Android ContentProvider query参数
  • myfwjy
  • myfwjy
  • 2016年07月11日 16:17
  • 1774

Android ContentProvider封装数据库和文件读写总结

本文是我各处东拼西凑加上自己实践的一个ContentProvider使用总结,留做后用,主要介绍ContentProvider的集成方法。 一、综述 ContentProvider是Android四...
  • u013478336
  • u013478336
  • 2016年02月23日 12:04
  • 1621

ContentProvider数据库共享之——MIME类型与getType()

前言:一、概述在上篇中,我们讲了通过共享数据库的增、删、改、查问题,但在生成PeopleContentProvider类时,由于其派生自ContentProvider,所以我们我们重写了数据库操作的i...
  • harvic880925
  • harvic880925
  • 2015年03月25日 14:03
  • 5403
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android学习之contentProvider
举报原因:
原因补充:

(最多只允许输入30个字)