3、ContentProvider
  数据在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据。ContentProvider实现多应用程序间的数据共享类
一般利用ContentProvider为需要共享的数据定义一个URI(统一资源定位符)
然后其他程序通过Context获得ContentResolver并将数据的URI传入即可

Android已为一些常用的数据创建ContentProvider,这些ContentProvider位于
android.provider包下,常用的就是手机上联系人信息,但是要取得相应的权限自己的应用程序才能访问
具体设置是在AndroidManifest.xml

 <uses-permission android:name="android.permission.READ_CONTACTS" />

对于ContentProvide重要的是数据模型和URI
数据模型:ContentProvide为所需要的数据创建表,每行代表一条记录,每条记录有唯一的'_ID'标识
URI:每个ContentProvide对外提供一个URI来标识自己的数据集

URI特点:
1、无法改变的标准前缀,包括;"content://"、"tel://"等。当前缀是"content://"时,说明通过一个Content Provider控制这些数据
2、URI的标识,它通过authorities属性声明,用于定义了是哪个ContentProvider提供这些数据。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的类名(数据路径)。例如;"content://com.example.contentprovide.myprovider"
3、如果URI中包含表示需要获取的记录的_ID;则就返回该id对应的数据,如果没有_ID,就表示返回全部

举个例子,如:

所有联系人的URI: content://contacts/people

某个联系人的URI: content://contacts/people/5

具体使用步骤:
1、在当前应用程序中定义一个ContentProvider

 public class MyProvider extends ContentProvider {

     @Override
public int delete(Uri arg0, String arg1, String[] arg2) {
// TODO Auto-generated method stub
return 0;
} @Override
public String getType(Uri arg0) {
// TODO Auto-generated method stub
return null;
} @Override
public Uri insert(Uri arg0, ContentValues arg1) {
// TODO Auto-generated method stub
return null;
} // 创建数据库,建表和插入数据
@Override
public boolean onCreate() {
// TODO Auto-generated method stub
SQLiteDatabase db =this.getContext().openOrCreateDatabase("mydb.db", Context.MODE_PRIVATE, null);
db.execSQL("create table tab(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
ContentValues values =new ContentValues();
values.put("name", "Hello ContentProvider!");
db.insert("tab", "_id", values);
db.close();
return true;
} // 查询
@Override
public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
String arg4) {
// TODO Auto-generated method stub
SQLiteDatabase db =this.getContext().openOrCreateDatabase("mydb.db", Context.MODE_PRIVATE, null);
Cursor c = db.query("tab", null, null, null, null, null,null);
return c;
} @Override
public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
// TODO Auto-generated method stub
return 0;
}

这里为了演示方便只实现创建和查询两个简单的方法

2、在当前应用程序的AndroidManifest.xml中注册此ContentProvider

 <provider android:name=".MyProvider" android:authorities="com.example.contentprovider.MyProvider"/>

3、其他应用程序通过ContentResolver和Uri来获取此ContentProvider的数据

 protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // 获取当前context
Context context = MainActivity.this; // 得到ContentResolver对象
ContentResolver resolver = context.getContentResolver(); // uri格式 "content://"、数据的路径、标示ID(可选)
Uri uri = Uri.parse("content://com.example.contentprovider.MyProvider");
Cursor c = resolver.query(uri, null, null, null, null); // 打印获取数据
c.moveToFirst();
for(int i=0; i<c.getCount(); i++){
int index = c.getColumnIndexOrThrow("name");
String src = c.getString(index);
Log.d("", src);
c.moveToNext();
}
}

日志打印:

  上面MyProvider代码和应用程序MainActivity代码不放在同一个包下是想说明ContentProvider不同程序间的数据共享,

但是注册获取权限那段代码要放在调用的程序包里。

  其实通过代码可以看出为了共享数据库.可以让数据库披上ContentProvider外衣,主要还是通过SQLiteDatabase去操作数据库。

当然对于已封装的共享数据。我们只要设置获取权限,通过ContentResolver就可以直接调用。

4、获取系统的联系人、媒体库信息

  对于系统程序的联系人、多媒体等信息可通过指定的Uri来获取。

  数据附录是获取本地联系人信息代码:

 public String getContactInfo(){
String result="";
ContentResolver resolver=getContentResolver();
//查询联系人
Cursor cursor=resolver.query(Contacts.CONTENT_URI, null, null, null, null);
int idIndex=cursor.getColumnIndex(Contacts._ID);
// 取得联系人名字 (显示出来的名字),实际内容在 ContactsContract.Contacts中
int nameIndex=cursor.getColumnIndex(Contacts.DISPLAY_NAME);
for (cursor.moveToFirst();(!cursor.isAfterLast());cursor.moveToNext()) {
//获取联系人ID
String contactId =cursor.getString(idIndex);
result=result+contactId+"\t\t\t";
result=result+cursor.getString(nameIndex)+"\t\t\t";
// 根据联系人ID查询对应的电话号码
Cursor phoneNumbers = resolver.query(CommonDataKinds.Phone.CONTENT_URI, null,
CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);
// 取得电话号码(可能存在多个号码)
while (phoneNumbers.moveToNext())
{
String strPhoneNumber = phoneNumbers.getString(phoneNumbers.getColumnIndex(CommonDataKinds.Phone.NUMBER));
result=result+strPhoneNumber+"\t\t\t";
}
phoneNumbers.close(); // 根据联系人ID查询对应的email
Cursor emails = resolver.query(CommonDataKinds.Email.CONTENT_URI, null,
CommonDataKinds.Email.CONTACT_ID + " = " + contactId, null, null);
// 取得email(可能存在多个email)
while (emails.moveToNext())
{
String strEmail = emails.getString(emails.getColumnIndex(CommonDataKinds.Email.DATA));
result=result+strEmail+"\t\t\t";
}
emails.close();
result=result+"\n";
}
cursor.close();
return result;
}

5、监听ContentProvider的数据改变

  随着ContentProvider的共享数据可能发生改变,要提供给有使用该共享数据的相应,具体步骤如下:

1).在ContentProvider类的insert\update\delete方法加入this.getContext().getContentResolver().notifyChange(URI,null);
其中URI表示监听的URI
null表示发送消息给任何人;
 
2).在访问者的类中调用如下方法:
context.getContentResolver().registerContentObserver(uri,true,new ContentObserver(new Handler()));
 
3).创建内部类继承ContentObserver并重写下面两个方法:
(1)带有Handler的构造函数;
(2)public void onChange(boolean selfChange); 此函数在内容提供者发出改变信号时就会被调用

参数selfChange为如果是自己改变的原因,则为true;如果不是自己改变的,则为false;

android学习日记13--数据存储之ContentProvide的更多相关文章

  1. Android 学习笔记之数据存储SharePreferenced+File

    学习内容: Android的数据存储.... 1.使用SharedPreferences来保存和读取数据... 2.使用File中的I/O来完成对数据的存储和读取...   一个应用程序,经常需要与用 ...

  2. android学习日记13--数据存储之SharedPreference

    android 数据存储 作为一个完整的应用程序,数据存储必不可少.android 提供了五种不同的数据存储方式:SharedPreferences.SQLite.ContentProvider.文件 ...

  3. android学习日记13--数据存储之File存储

    4.文件存储File File即传统的I/O 流存储文件,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的 ...

  4. android学习日记13--数据存储之SQLite

    2.SQLite 开源轻量级数据库,支持92-SQL标准,主要用于嵌入式系统,只占几百K系统资源此外,SQLite 不支持一些标准的 SQL 功能,特别是外键约束(FOREIGN KEY constr ...

  5. android学习日记05--Activity间的跳转Intent实现

    Activity间的跳转 Android中的Activity就是Android应用与用户的接口,所以了解Activity间的跳转还是必要的.在 Android 中,不同的 Activity 实例可能运 ...

  6. android学习日记03--常用控件checkbox/radiobutton

    常用控件3.checkbox 复选框,确定是否勾选,点击一下勾选,点击第二下取消,当有一系列备选项时适合用checkbox控件,方便用户提交数据. 贴上例子Activity的java代码 packag ...

  7. android学习日记03--常用控件button/imagebutton

    常用控件 控件是对数据和方法的封装.控件可以有自己的属性和方法.属性是控件数据的简单访问者.方法则是控件的一些简单而可见的功能.所有控件都是继承View类 介绍android原生提供几种常用的控件bu ...

  8. Android开发8:数据存储(二)——SQLite数据库和ContentProvider的使用

    前言 啦啦啦各位小伙伴们许久不见了~学期末和过年期间自己忙着做其他事没能及时更新Android开发系列课程的博客,实在是罪过罪过~ 好啦~废话不多说,进入我们今天的主题.今天我们将和大家学习其他的数据 ...

  9. android学习日记03--常用控件Dialog

    常用控件 9.Dialog 我们经常会需要在Android界面上弹出一些对话框,比如询问用户或者让用户选择.这些功能我们叫它Android Dialog对话框 对话框,要创建对话框之前首先要创建Bui ...

随机推荐

  1. 桶排序-Node.js-对象排序

    const b = [{index:5,name:"s5"}, {index:2,name:"s2"}, {index:3,name:"s3" ...

  2. SCAU 10690 分面包

    10690 分面包 时间限制:1000MS  内存限制:65535K 题型: 编程题   语言: 无限制 Description 在大一的时候,XCC还在stu union打酱油~~~~和十三还有奶子 ...

  3. SharePoint咨询师之路:备份和恢复系列三 - 备份web和服务应用程序

    本系列包括: 备份服务器场和配置 备份web和服务应用程序 备份内容数据库 备份网站集 备份自定义项 备份web应用程序和服务应用程序一样有三种方式:SharePoint管理中心网站.Windows  ...

  4. 如何判断Android设备是手机还是平板?

    转自:http://blog.csdn.net/zuolongsnail/article/details/8682950 Android开发需要适配手机和平板,有些需求在实现中就要判断设备是手机还是平 ...

  5. JXSE and Equinox Tutorial, Part 1

    http://java.dzone.com/articles/jxse-and-equinox-tutorial-part —————————————————————————————————————— ...

  6. 安装php5.5

    安装php5.5 ./configure --prefix=/usr/local/php5.5.14/ --with-apxs2=/usr/local/apache2.2.27/bin/apxs -- ...

  7. 配置Synergy(Server : XP, client: Win7)

    此文只是为了Mark一下配置方法,以防以后重装系统的时候,忘记.   首先,因为我的Server机器是XP,所以要求两台机器,都是安装的x86的版本,而不能是x64的版本. 我用的版本是1.4.11, ...

  8. How Tomcat Works(十四)

    我们已经知道,在tomcat中有四种类型的servlet容器,分别为Engine.Host.Context 和Wrapper,本文接下来对tomcat中Wrapper接口的标准实现进行说明. 对于每个 ...

  9. uva 542 - France '98(概率)

    题目链接:uva 542 - France '98 题目大意:有16支球队比赛,给出16支球队的名称,然后给出16*16的表格,g[i][j] 表示i队胜j队的概率,问说16支球队获得总冠军的概率. ...

  10. 关于WebPlayer Sandbox的小节

    不可以像其他build target一样读写I/O 不可以call一些private或者internal methord 只要在一个top level的domain下可以不需要xml dmain po ...