一.什么是ContentProvider?

ContentProvider直译过来就是内容提供者,主要作用就是A应用提供接口给B应用调用数据,和之前介绍的sharedPreference和直接开放文件访问类似,都是共享应用程序数据,不同的是之前的两种文件格式可能完全不同,如可能为xml,txt,sql等等,这里ContentProvider返回的数据格式是统一的,因此应用的更为广泛一点.

二.实例

这里使用的是A应用通过ContentProvider共享数据给B应用.这里A应用用的是前文中的android_db里的person表.B应用是新建的android_content_provider程序.

1.新创建android_content_provider应用程序

2.访问android_db共享的数据

创建好了应用程序以后,

/android_content_provider/src/com/example/android_content_provider/ContentProvider.java

package com.example.android_content_provider;

import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log; public class ContentProvider extends Activity { private static String tag = "ContentProvider.class"; /**
* Called when the activity is first created.
*/ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//内容解析者
ContentResolver contentResolver = getContentResolver();
Uri uri = Uri.parse("content://com.amos.android_db.provider.PersonProvider/persons");
Cursor cursor = contentResolver.query(uri, null, null, null, null);
while(cursor.moveToNext()){
String name = cursor.getString(cursor.getColumnIndex("name"));
int age = cursor.getInt(cursor.getColumnIndex("age"));
System.out.println("name:"+name+" age:"+age);
Log.d(tag,"用户名:"+name+" 年龄:"+age);
}
}
}

3.android_db开放共享数据接口

1)开放一个uri

/android_db/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.amos.android_db"
android:versionCode="1"
android:versionName="1.0">
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="com.amos.android_db"></instrumentation>
<uses-sdk android:minSdkVersion="7"/>
<application android:label="@string/app_name">
<uses-library android:name="android.test.runner"/>
<activity android:name="MyActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!--给内容提供者提供定义一个uri,一般建议使用包名+类名,以供其它程序调用 -->
<provider android:authorities="com.amos.android_db.provider.PersonProvider" android:name=".provider.PersonProvider">

</provider>
</application>
</manifest>

2).定义路径匹配(继承ContentProvider类)

/android_db/src/com/amos/android_db/provider/PersonProvider.java
package com.amos.android_db.provider;

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;
import android.util.Log;
import com.amos.android_db.MyDBHelper;
import com.amos.android_db.dao.Person;
import com.amos.android_db.dao.PersonDao; import java.util.List; /**
* Created by amosli on 14-6-17.
*/
public class PersonProvider extends ContentProvider { //创建一个路径识别器
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码,也就是说如果找不到匹配的类型,返回-1
private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final int ALL_PERSON = 1;
private static final int PERSON = 2;
private static final int OTHER = 3; private static String tag="PersonProvider.class"; static{
//1.指定一个路径的匹配规则
//如果路径满足content://com.amos.android_db.provider.PersonProvider/persons,返回值就是(ALL_PERSON)=1
uriMatcher.addURI("com.amos.android_db.provider.PersonProvider","persons",ALL_PERSON); //2.如果路径满足content://com.amos.android_db.provider.PersonProvider/person/3,返回值就是(PERSON)=2
//#号为通配符
uriMatcher.addURI("com.amos.android_db.provider.PersonProvider","person/#",PERSON);
//3.如果路径满足content://com.amos.android_db.provider.PersonProvider/other,返回值就是(OTHER)=3
uriMatcher.addURI("com.amos.android_db.provider.PersonProvider","other",OTHER); } /**
* 一般是对象第一次被创建时调用的方法
*
* @return
*/
@Override
public boolean onCreate() { return false;
} /**
* 让别人去调用返回结果
*
* @param uri
* @param projection 选择的列
* @param selection 查询条件
* @param selectionArgs 查询条件的value
* @param sortOrder 排序
* @return
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
int result = uriMatcher.match(uri);
switch(result){
//如果路径满足content://com.amos.android_db.provider.PersonProvider/persons,返回值就是(ALL_PERSON)=1
case ALL_PERSON:
PersonDao dao = new PersonDao(this.getContext());
return dao.findAllByCursor(); //2.如果路径满足content://com.amos.android_db.provider.PersonProvider/person/3,返回值就是(PERSON)=2
case PERSON:
long id = ContentUris.parseId(uri);
SQLiteDatabase database = new MyDBHelper(this.getContext()).getReadableDatabase();
if(database.isOpen()){
database.execSQL("select * person where personid = "+id);
return database.query("person", null, "personid", new String[]{id + ""}, null, null, null);
//不要关闭数据库,否则就没有数据了.
}
case OTHER:
Log.d(tag,"我是其他匹配规则!");
break;
default:
throw new RuntimeException("出错了!!"); } return null;
} @Override
public String getType(Uri uri) {
return null;
} @Override
public Uri insert(Uri uri, ContentValues values) {
return null;
} @Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
} @Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return 0;
}
}

4.效果图

首先,将android_db部署到avd上,其次,运行android_content_provider项目,最后,查看log输出.

5.出现的问题

1).报空指针错误

.....

at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.example.android_content_provider.ContentProvider.onCreate(ContentProvider.java:21)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
.....

这种问题很有可能是路径名称不对,注意提供的接口名称保持一致;并且保证获取数据的接口是正常的,即android_db里获取person表的内容是正常的.

2).intelij中的logcat中看不到log

注意选择Android--->选择要查看Log的进程--->点击上面的双向箭头进行切换日志展示信息.

 6.扩展

1),查询,增加,删除,修改的接口全部实现

上面已经实现了查询的接口,这里将实现另外三个接口:

        //4.插入数据,如果路径满足content://com.amos.android_db.provider.PersonProvider/insert,返回值就是(INSERT)=4
uriMatcher.addURI("com.amos.android_db.provider.PersonProvider", "insert", INSERT);
//5.删除数据,如果路径满足content://com.amos.android_db.provider.PersonProvider/delete,返回值就是(DELETE)=5
uriMatcher.addURI("com.amos.android_db.provider.PersonProvider", "delete", DELETE);
//6.更新数据,如果路径满足content://com.amos.android_db.provider.PersonProvider/update,返回值就是(UPDATE)=6
uriMatcher.addURI("com.amos.android_db.provider.PersonProvider", "update", UPDATE);

对应的实现:

 @Override
public Uri insert(Uri uri, ContentValues values) { //content://com.amos.android_db.provider.PersonProvider/insert
int result = uriMatcher.match(uri);
switch (result) {
case INSERT:
SQLiteDatabase database = myDBHelper.getWritableDatabase();
if (database.isOpen()) {
database.insert("person", null, values);
}
return uri; default:
throw new RuntimeException("无法识别该URI,出错了!!");
} } @Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
//删除操作
//content://com.amos.android_db.provider.PersonProvider/delete
int result = uriMatcher.match(uri);
switch (result) {
case DELETE:
SQLiteDatabase database = myDBHelper.getWritableDatabase();
return database.delete("person", selection, selectionArgs); default:
throw new RuntimeException("无法识别该URI,出错了!!");
} } @Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
//更新操作
//content://com.amos.android_db.provider.PersonProvider/update
int result = uriMatcher.match(uri);
switch (result) {
case UPDATE:
SQLiteDatabase database = myDBHelper.getWritableDatabase();
return database.update("person", values, selection, selectionArgs); default:
throw new RuntimeException("无法识别该URI,出错了!!");
} }

//返回值的类型

   @Override
public String getType(Uri uri) {
int result = uriMatcher.match(uri);
switch (result){
case ALL_PERSON:
return "List<Person>";
case PERSON:
return "Person";
default:return null;
}
}

2)测试 

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ContentProviderTest"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7"/>
<instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.example.ContentProviderTest"/> <application android:label="@string/app_name">
<uses-library android:name="android.test.runner"/>
<activity android:name="MyActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

加入加粗的两行,配置好测试的环境.

/ContentProviderTest/src/com/example/ContentProviderTest/test/TestCase.java

package com.example.ContentProviderTest.test;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.net.Uri;
import android.test.AndroidTestCase; /**
* Created by amosli on 14-6-19.
*/
public class TestCase extends AndroidTestCase { public void testInsert(){
ContentResolver contentResolver = getContext().getContentResolver();
Uri uri = Uri.parse("content://com.amos.android_db.provider.PersonProvider/insert");
ContentValues values = new ContentValues();
values.put("name", "bill");
values.put("age", 18);
contentResolver.insert(uri, values);
}
public void testDelete(){
ContentResolver contentResolver = getContext().getContentResolver();
Uri uri = Uri.parse("content://com.amos.android_db.provider.PersonProvider/delete");
contentResolver.delete(uri,"name=?",new String[]{"amos96"});
}
public void testUpdate(){
ContentResolver contentResolver = getContext().getContentResolver();
Uri uri = Uri.parse("content://com.amos.android_db.provider.PersonProvider/update");
ContentValues contentValues = new ContentValues();
contentValues.put("name","jack");
contentValues.put("age",30);
contentResolver.update(uri,contentValues,"name=?",new String[]{"amos97"});
} }

3)效果图:

插入数据(insert方法),bill

删除数据(delete方法),amos96

更新数据(update方法 ),amos97

本文源码:

https://github.com/amosli/android_basic/tree/android_db

https://github.com/amosli/android_basic/tree/content_provoider

https://github.com/amosli/android_basic/tree/android_contentProviderTest

Android学习---通过内容提供者(ContentProvider)操作另外一个应用私有数据库的内容的更多相关文章

  1. [Android Pro] 监听内容提供者ContentProvider的数据变化

    转载自:http://blog.csdn.net/woshixuye/article/details/8281385 一.提出需求 有A,B,C三个应用,B中的数据需要被共享,所以B中定义了内容提供者 ...

  2. Android中内容提供者ContentProvider的详解

    1.什么是ContentProvider 首先,ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少. ContentProvider为不 ...

  3. Android开发14——监听内容提供者ContentProvider的数据变化

    一.提出需求 有A,B,C三个应用,B中的数据需要被共享,所以B中定义了内容提供者ContentProvider:A应用修改了B应用的数据,插入了一条数据.有这样一个需求,此时C应用需要得到数据被修改 ...

  4. Android基础内容提供者ContentProvider的使用详解(转)

    1.什么是ContentProvider 首先,ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少. ContentProvider为不 ...

  5. 安卓第十四天笔记-内容提供者(ContentProvider)

    安卓第十四天笔记-内容提供者(ContentProvider) ContentProvider--内容提供者 1.ContentProvider简介 ContentProvider是不同应用程序之间进 ...

  6. [Android Pro] 内容提供者ContentProvider的基本使用

    一.ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.ContentProvider为存储和获取数据提 ...

  7. Android开发13——内容提供者ContentProvider的基本使用

    一.ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.ContentProvider为存储和获取数据提 ...

  8. Android之内容提供者ContentProvider的总结

    本文包含以下知识点: ContentProvider Uri 的介绍 ContentResolver: 监听ContentProvider的数据改变 一:ContentProvider部分 Conte ...

  9. Android学习十九:ContentProvider初步

    一.Content Provider基本概念 1.ContentProvider为存储和获取数据提供了统一的接口.ContentProvide对数据进行封装.不用关心数据存储的细节.使用表的形式来组织 ...

随机推荐

  1. NodeJs 创建 Web 服务器

    以下是演示一个最基本的 HTTP 服务器架构(使用8081端口),创建 ser.js 文件,代码如下所示: var http = require('http'); var fs = require(' ...

  2. HTML 浏览器显示控制

    //强制浏览器以最高版本运行页面 <meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1" ...

  3. Unable to install breakpoint in

    Unable to install breakpoint inXXXX due to missing line number attributes.modify compiler options to ...

  4. V8 data struct

    参考: [1]. 使用 Google V8 引擎开发可定制的应用程序: http://www.ibm.com/developerworks/cn/opensource/os-cn-v8engine/ ...

  5. 《JavaScript高级程序设计》学习笔记(2)--JS运算符详解

    欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 思维导图 前面对JS的运算符的操作很多细节的东西没有提及,今天给大家分享一张网上找的思维导图,对这一部 ...

  6. android 双击返回按钮退出程序。

    重写   onKeyDown()方法. @Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode == K ...

  7. 关于iOS10的允许访问用户数据产生的问题

    不知道这个问题是什么时候出现的,直到我重写项目已应对IPv6的审核. 先前没有加引导页面,打开app直接进入主控制器.当弹出允许访问用户数据窗口的时候,主页面的数据是不加载的. 当用户未允许访问数据之 ...

  8. 有一字符串,包含n个字符。写一函数,将此字符串中从第m个字符开始的全部字符复制成为另一个字符串。

    [提交][状态][讨论版] 题目描述 有一字符串,包含n个字符.写一函数,将此字符串中从第m个字符开始的全部字符复制成为另一个字符串. 输入 数字n 一行字符串 数字m 输出 从m开始的子串 样例输入 ...

  9. linux下wps,系统缺失字体:wingdings、wingdings 2、wingdings3

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAArcAAACdCAIAAAAhV8dZAAAgAElEQVR4nOzdd1wT9/8H8OvXfjvtt8

  10. 封装、调用ajax

    1.JavaScript代码 //封装ajaxfunction ajax(obj) { var xhr = new createXHR(); obj.url = obj.url + '?rand=' ...