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. 快速入门linux系统的iptables防火墙 1 本机与外界的基本通信管理

    概述 iptables是一种运行在linux下的防火墙组件,下面的介绍可以快速的学习iptables的入门使用. 特点(重要) 它的工作逻辑分为 链.表.规则三层结构. 数据包通过的时候,在对应表中, ...

  2. 【开源项目之路】jquery的build问题

    在刚开始clone了jquery到本地build的时候,就遇到了问题. “ENORESTARGET No tag found that was able to satisfy ...” 提示为bowe ...

  3. Windows Azure 虚拟网络配置(Site to Site)

    上篇我们创建了Point to Site的虚拟网络连接,来满足客户端到云端网络的连接.本篇文章我们将创建Site to Site的虚拟网络连接,以满足本地网络到云端的网络连接. 创建与配置过程与上篇较 ...

  4. shell学习目录

    1. 了解shell 2. shell 入门基础 3. Shell脚本文件中常用的操作语句

  5. ubuntu cloud-archive 软件包 无法验证包来源

  6. Spark RDD概念学习系列之RDD的转换(十)

    RDD的转换 Spark会根据用户提交的计算逻辑中的RDD的转换和动作来生成RDD之间的依赖关系,同时这个计算链也就生成了逻辑上的DAG.接下来以“Word Count”为例,详细描述这个DAG生成的 ...

  7. UNITY3D MAC版本破解

    百度网盘下载地址: http://pan.baidu.com/s/1eQmvLqa#path=%252F 包含本体和破解文件 首先说明一下,如果是公司做开发建议去购买正版. 之前网上也有很多人贴出了破 ...

  8. js 生成随机数

    <script>   function GetRandomNum(Min,Max){   var Range = Max - Min;   var Rand = Math.random() ...

  9. rdlc Report Viewer Configuration Error

    主要是web.config没有配置 方法参考http://msdn.microsoft.com/zh-cn/library/ms251661.aspx

  10. python 加密解密(base64, AES)

    1. 使用base64 s1 = base64.encodestring('hello world') s2 = base64.decodestring(s1) print s1, s2 结果 1 2 ...