应用场景:html
在Android官方指出的Android的数据存储方式总共有五种,分别是:Shared Preferences、网络存储、文件存储、外储存储、SQLite。可是咱们知道通常这些存储都只是在单独的一个应用程序之中达到一个数据的共享,并且这些知识在前面我都有介绍,有时候咱们须要操做其余应用程序的一些数据,例如咱们须要操做系统里的媒体库、通信录等,这时咱们就可能经过ContentProvider来知足咱们的需求了java
ContentProvider概述:android
ContentProvider向咱们提供了咱们在应用程序以前共享数据的一种机制,而咱们知道每个应用程序都是运行在不一样的应用程序的,数据和文件在不一样应用程序之间达到数据的共享不是没有可能,而是显得比较复杂,而正好Android中的ContentProvider则达到了这一需求,好比有时候咱们须要操做手机里的联系人,手机里的多媒体等一些信息,咱们均可以用到这个ContentProvider来达到咱们所需。web
如何理解ContentProvidersql
上面说了一大堆ContentProvider的概述,可能你们仍是不太特别理解ContentProvider究竟是干什么的,那么咱们以一个网站来形象的描述这个ContentProvider吧,能够这么理解为ContentProvider就是一个网站,它向咱们去访问网站这里的数据达到了一种可能,它就是一个向外提供数据的接口。那么既然它是向外提供数据,咱们有时候也须要去修改数据,这时咱们就能够用到另一个类来实现这个对数据的修改ContentResolver类,这个类就能够经过URI来操做数据。至于这些类的做用及描述在下面就会一一的介绍到。网络
如何实现ContentProviderapp
理解了ContentProvider类,那么咱们怎么去实现ContentProvider呢?怎么样让外部程序去访问或者修改咱们的数据呢?这样的一个操做实际上是很是简单的,咱们只须要下面的两步就能够实现ContentProvideride
一、 编写一个实现ContentProvider的在,这个子类必需要实现一些必须实现的方法,在ContentProvider类里面,有一系列针对于数据的增、删、改、查等方法工具
二、 ContentProvider也是Android中的四大组件,所以也必须在AndroidMainfest.xml中完成对ContentProvider的注册。注册方式为:oop
与ContentProvider相关操做的类介绍
从Uri谈起
什么是Uri?
Uri是指通用资源标志符

A:前缀代表数据受控于一个内容提供者。它从不修改,也就是schema
B:是指在AndroidMainfest.xml中咱们注册的provider中的android:authorities属性所对应的
C:具体操做于哪一个条目
D:具体指定到哪一个条目下的哪条记录
再看它的类结构和经常使用方法:
Uri

在这个里它是没有构造方法的,它一般经过下面的这个方法来返回一个Uri对象
方法名称 |
描述 |
public static Uri parse (String uriString) |
经过一个传入的字符串来构造一个Uri对象 |
熟悉完Uri类再看与之相关的另外两个类
UriMatcher类:

由于Uri表明了要操做的数据,因此咱们常常须要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操做Uri的工具类,分别为UriMatcher 和ContentUris 。掌握它们的使用,会便于咱们的开发工做。
先看下它比较经常使用的几个方法:
方法名称 |
描述 |
public void addURI (String authority, String path, int code) |
往UriMatcher类里添加一个拼凑的Uri,在此咱们能够理解为UriMatcher为一个Uri的容器,为个容器里面包含着咱们即将可能要操做的Uri,它用于咱们业务逻辑的处理,特别是第三个参数code,若是经过下面的match()方法匹配成功就返回这个code值 |
public int match (Uri uri) |
与传入的Uri匹配,它会首先与找咱们以前经过addURI方法添加进来的Uri匹配,若是匹配成功就返回以前咱们设置的code值,不然返回一个UriMatcher.NO_MATCH常量值为-1 |
熟悉完上面的方法,那么咱们再来看它如何使用:
UriMatcher类用于匹配Uri,它的用法以下:
UriMatcher类的用法
首先第一步把你须要匹配Uri路径所有给注册上,以下:
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
//若是match()方法匹配content:// com.jiahui.provider.myprovider/person路径,返回匹配码为1
sMatcher.addURI(“com.jiahui.provider.myprovider”, “person”, 1);//添加须要匹配uri,若是匹配就会返回匹配码
//若是match()方法匹配content:// com.jiahui.provider.myprovider /person/230路径,返回匹配码为2
sMatcher.addURI(“com.jiahui.provider.myprovider”, “person/#”, 2);//#号为通配符
switch (sMatcher.match(Uri.parse("content:// com.jiahui.provider.myprovider /person/10"))) {
case 1
break;
case 2
break;
default://不匹配
break;
}
注册完须要匹配的Uri后,就可使用sMatcher.match(uri)方法对输入的Uri进行匹配,若是匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://cn.itcast.provider.personprovider/person路径,返回的匹配码为1
再看另一个工具类
ContentUris:

它用于在Uri后面追加一个ID或者解析出传入的Uri所带上的ID值,经常使用的两个方法以下:
方法名称 |
描述 |
public static Uri withAppendedId (Uri contentUri, long id) |
用于为路径加上ID部分 |
public static long parseId (Uri contentUri) |
从路径中获取ID部分 |
熟悉完上面所说起的相关的类,接下来咱们再看这个ContentProvider核心类
ContentProvider

经常使用方法
方法名称 |
描述 |
public abstract boolean onCreate () |
在ContentProvider建立后被调用。 |
public abstract Uri insert (Uri uri, ContentValues values) |
根据Uri插入values对就的数据 |
public abstract int delete (Uri uri, String selection, String[] selectionArgs) |
根据Uri删除selection指定的条件所匹配的所有记录 |
public abstract int update (Uri uri, ContentValues values, String selection, String[] selectionArgs) |
根据Uri修改selection指定的条件所匹配的所有记录 |
public abstract Cursor query (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) |
根据Uri查询出selection指定的条件所匹配的所有记录,而且能够指定查询哪些列(projection),以什么方式(sortOrder)排序 |
public abstract String getType (Uri uri) |
返回当前Uri所数据的MIME类型,若是该Uri对应的数据可能包括多条记录,那么MIME类型字符串就是以vnd.android.cursor.dir/开头,若是Uri对应的数据只包含一条记录,那么MIME类型字符串就是以vnd.android.cursor.item/开头 |
既然咱们知道了ContentProvider类是向外提供数据的一种机制,那么在以前咱们也说过要想来操做这个对外提供的数据,咱们就用到了另一个类:
ContentResolver

在这个类里面也定义了一系列的增、删、改、查方法,与其ContentProvider定义的方法基本上相同,在此再也不复核。读者能够本身查阅相关文档。
可能你们在这里仍是有点理不清这些类的一些关系,特别是ContentResolver与ContentProvider与Uri类的关系,那么我上张图吧,或许对你们有所帮助:

好了熟悉完上面所述的这么多类那么咱们就在实践中见证真理吧:
实例:
实现效果:

代码实现:
先开发咱们本身的ContentProvider:
- package com.jiahui.provider;
-
- import com.jiahui.db.DBHelper;
-
- 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 DBHelper dbHelper;
- // 定义一个UriMatcher类
- private static final UriMatcher MATCHER = new UriMatcher(
- UriMatcher.NO_MATCH);
- private static final int PERSONS = 1;
- private static final int PERSON = 2;
- static {
- MATCHER.addURI("com.jiahui.provider.myprovider", "person", PERSONS);
- MATCHER.addURI("com.jiahui.provider.myprovider", "person/#", PERSON);
-
- }
- @Override
- public boolean onCreate() {
- System.out.println("---oncreate----");
- dbHelper = new DBHelper(this.getContext());
- return false;
- }
-
- // 查询数据
- @Override
- public Cursor query(Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
-
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- switch (MATCHER.match(uri)) {
- case PERSONS:
- // 查询全部的数据
- return db.query("person", projection, selection, selectionArgs,
- null, null, sortOrder);
-
- case PERSON:
- // 查询某个ID的数据
- // 经过ContentUris这个工具类解释出ID
- long id = ContentUris.parseId(uri);
- String where = " _id=" + id;
- if (!"".equals(selection) && selection != null) {
- where = selection + " and " + where;
-
- }
-
- return db.query("person", projection, where, selectionArgs, null,
- null, sortOrder);
- default:
-
- throw new IllegalArgumentException("unknow uri" + uri.toString());
- }
-
- }
-
- // 返回当前操做的数据的mimeType
- @Override
- public String getType(Uri uri) {
- switch (MATCHER.match(uri)) {
- case PERSONS:
- return "vnd.android.cursor.dir/person";
- case PERSON:
- return "vnd.android.cursor.item/person";
- default:
- throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
- }
- }
-
- // 插入数据
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- Uri insertUri = null;
- switch (MATCHER.match(uri)) {
- case PERSONS:
-
- long rowid = db.insert("person", "name", values);
- insertUri = ContentUris.withAppendedId(uri, rowid);
-
- break;
-
- default:
- throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
- }
- return insertUri;
- }
-
- // 删除数据
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- SQLiteDatabase db = dbHelper.getWritableDatabase();
- int count = 0;
- switch (MATCHER.match(uri)) {
- case PERSONS:
- count = db.delete("person", selection, selectionArgs);
- return count;
-
- case PERSON:
- long id = ContentUris.parseId(uri);
- String where = "_id=" + id;
- if (selection != null && !"".equals(selection)) {
- where = selection + " and " + where;
- }
- count = db.delete("person", where, selectionArgs);
- return count;
-
- default:
- throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
- }
- }
-
- // 更新数据
- @Override
- public int update(Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
-
- SQLiteDatabase db = dbHelper.getWritableDatabase();
-
- int count = 0;
- switch (MATCHER.match(uri)) {
- case PERSONS:
- count = db.update("person", values, selection, selectionArgs);
- break;
- case PERSON:
- // 经过ContentUri工具类获得ID
- long id = ContentUris.parseId(uri);
- String where = "_id=" + id;
- if (selection != null && !"".equals(selection)) {
- where = selection + " and " + where;
- }
- count = db.update("person", values, where, selectionArgs);
- break;
- default:
- throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
- }
- return count;
- }
-
- }
千万别忘记了要在AndroidMainfest.xml文件中注册这个组件哦:
- <provider
- android:authorities="com.jiahui.provider.myprovider"
- android:name=".MyProvider" >
- </provider>
而后在一个主Activity编写一些实现代码:
- package com.jiahui.provider;
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- import android.app.Activity;
- import android.content.ContentResolver;
- import android.content.ContentUris;
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.Intent;
- import android.database.Cursor;
- import android.net.Uri;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.view.View;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ListView;
- import android.widget.SimpleAdapter;
- import android.widget.Toast;
-
- import com.jiahui.model.Person;
-
- public class ContentProviderDemoActivity extends Activity {
-
- private Button btnadd, btnqueryall;
- private EditText edtname, edtage;
-
- private ListView lvall;
-
- private List<Person> persons;
- private SimpleAdapter simpleAdapter;
- private Handler handler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
-
- List<Map<String, Object>> data = (List<Map<String, Object>>) msg.obj;
-
- System.out.println(data.size());
-
-
- simpleAdapter = new SimpleAdapter(
- ContentProviderDemoActivity.this, data, R.layout.list_item,
- new String[] { "id", "name", "age" }, new int[] {
- R.id.tvId, R.id.tvname, R.id.tvage });
-
- lvall.setAdapter(simpleAdapter);
-
- }
-
- };
-
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- persons = new ArrayList<Person>();
-
- btnqueryall = (Button) this.findViewById(R.id.btnqueryall);
- btnadd = (Button) this.findViewById(R.id.btnadd);
- edtname = (EditText) this.findViewById(R.id.edtname);
- edtage = (EditText) this.findViewById(R.id.edtage);
- lvall = (ListView) this.findViewById(R.id.lvall);
-
- btnadd.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- ContentResolver contentResolver = ContentProviderDemoActivity.this
- .getContentResolver();
-
- Uri url = Uri
- .parse("content://com.jiahui.provider.myprovider/person");
- ContentValues values = new ContentValues();
- values.put("name", edtname.getText().toString());
- values.put("age", edtage.getText().toString());
- Uri result = contentResolver.insert(url, values);
-
- System.out.println(result.toString());
-
- if (ContentUris.parseId(result)>0) {
- Toast.makeText(ContentProviderDemoActivity.this, "添加成功", Toast.LENGTH_LONG).show();
- //添加成功后再启动线程查询
- MyThread thread = new MyThread(ContentProviderDemoActivity.this);
- thread.start();
- }
- }
- });
- //查询全部
- btnqueryall.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- MyThread thread = new MyThread(ContentProviderDemoActivity.this);
- thread.start();
- }
- });
-
- lvall.setOnItemClickListener(new OnItemClickListener() {
-
- @Override
- public void onItemClick(AdapterView<?> parent, View view,
- int position, long id) {
- // Toast.makeText(ContentProviderDemoActivity.this, position,
- // Toast.LENGTH_LONG).show();
- System.out.println("position:" + position);
-
- Person person = persons.get(position);
- Bundle bundle = new Bundle();
- bundle.putInt("id", person.getId());
-
- bundle.putString("name", person.getName());
-
- bundle.putInt("age", person.getAge());
-
- Intent intent = new Intent(ContentProviderDemoActivity.this,
- ItemActivity.class);
- intent.putExtra("item", bundle);
- startActivityForResult(intent, 1);
-
- }
- });
-
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-
- if (resultCode==2) {
- MyThread thread = new MyThread(ContentProviderDemoActivity.this);
- thread.start();
-
- }
-
- }
-
-
- class MyThread extends Thread {
-
- Context context;
-
- public MyThread(Context context) {
- //必定要清空。不然会 有问题,每执行一次都会把以前的所有的item加进去
- persons.clear();
- lvall.setAdapter(null);
-
- this.context = context;
- }
-
- @Override
- public void run() {
-
- Uri url = Uri
- .parse("content://com.jiahui.provider.myprovider/person");
-
- Cursor cursor = context.getContentResolver().query(url,
- new String[] { "_id", "name", "age" }, null, null, "_id");
-
- while (cursor.moveToNext()) {
-
- // System.out.println("_id:"
- // + cursor.getInt(cursor.getColumnIndex("_id")));
- // System.out.println("name:"
- // + cursor.getString(cursor.getColumnIndex("name")));
- // System.out.println("age:"
- // + cursor.getInt(cursor.getColumnIndex("age")));
- Person person = new Person();
- person.setId(cursor.getInt(cursor.getColumnIndex("_id")));
- person.setName(cursor.getString(cursor.getColumnIndex("name")));
- person.setAge(cursor.getInt(cursor.getColumnIndex("age")));
- persons.add(person);
-
- }
-
- cursor.close();
-
- List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
-
- Map<String, Object> map=null;
- for (int i = 0; i < persons.size(); i++) {
-
- map = new HashMap<String, Object>();
-
- map.put("id", persons.get(i).getId());
- map.put("name", persons.get(i).getName());
-
- map.put("age", persons.get(i).getAge());
- data.add(map);
-
- }
- if (data.size()>=persons.size()) {
-
- }
- Message msg = handler.obtainMessage();
- msg.obj = data;
- handler.sendMessage(msg);
- }
-
- }
-
- }
ItemActivity代码:
- package com.jiahui.provider;
-
- import android.app.Activity;
- import android.content.ContentResolver;
- import android.content.ContentValues;
- import android.content.Intent;
- import android.net.Uri;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.TextView;
- import android.widget.Toast;
-
- public class ItemActivity extends Activity {
-
- private EditText edt_item_name;
- private EditText edt_item_age;
- private EditText edt_item_id;
- private Button btndel, btnupdate;
-
- private Intent intent;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.item);
-
- edt_item_id = (EditText) this.findViewById(R.id.edt_item_id);
- edt_item_id.setEnabled(false);// 控制不可用
- edt_item_name = (EditText) this.findViewById(R.id.edt_item_name);
- edt_item_age = (EditText) this.findViewById(R.id.edt_item_age);
- // 获得传过来的数据
- btndel = (Button) this.findViewById(R.id.btndel);
- btnupdate = (Button) this.findViewById(R.id.btnupdate);
-
- intent = getIntent();
-
- Bundle bundle = intent.getBundleExtra("item");
-
- int id = bundle.getInt("id");
- System.out.println("id----" + id);
- String name = bundle.getString("name");
- int age = bundle.getInt("age");
-
- edt_item_id.setText(String.valueOf(id));
- edt_item_name.setText(name);
- edt_item_age.setText(String.valueOf(age));
-
- btndel.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
- ContentResolver contentResolver = ItemActivity.this
- .getContentResolver();
- // 构建Uri
- String url = "content://com.jiahui.provider.myprovider/person/"
- + edt_item_id.getText();
- Uri uri = Uri.parse(url);
-
- int result = contentResolver.delete(uri, null, null);
- System.out.println("delete result:" + result);
-
- if (result >= 1) {
- Toast.makeText(ItemActivity.this, "删除成功", Toast.LENGTH_LONG)
- .show();
- ItemActivity.this.setResult(2);
- ItemActivity.this.finish();
- }
-
- }
- });
-
- btnupdate.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- ContentResolver contentResolver = ItemActivity.this
- .getContentResolver();
- // 构建Uri
- String url = "content://com.jiahui.provider.myprovider/person/"
- + edt_item_id.getText();
- Uri uri = Uri.parse(url);
- ContentValues values = new ContentValues();
- values.put("name", edt_item_name.getText().toString());
- values.put("age",
- Integer.parseInt(edt_item_age.getText().toString()));
- int result = contentResolver.update(uri, values, null, null);
- System.out.println("update result:" + result);
- if (result >= 1) {
- Toast.makeText(ItemActivity.this, "更新成功", Toast.LENGTH_LONG)
- .show();
- ItemActivity.this.setResult(2);
- ItemActivity.this.finish();
- }
-
- }
- });
-
- }
-
- }
特别说明:这个例子也是与以前讲过的一讲与SQLite知识相关的代码中一个类,读者须要用到以前的DBHelper类,请自行拷贝。