//此系列博文是《第一行Android代码》的学习笔记,如有错漏,欢迎指正!

  内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。当一个应用程序通过内容提供器对其数据提供了外部访问接口,任何其他的应用程序就都可以对这部分数据进行访问。Android 系统中自带的电话簿、短信、媒体库等程序都提供了类似的访问接口,这就使得第三方应用程序可以充分地利用这部分数据来实现更好的功能。

一、ContentResolver 的基本用法

  对于每一个应用程序来说,如果想要访问内容提供器中共享的数据,就一定要借助ContentResolve 类——通过 Context 中的 getContentResolver()方法获取到该类的实例。ContentResolver 中提供了一系列的方法用于对数据进行 CRUD 操作,这些操作与SQL相似,不过在方法参数上有点区别:与SQL相比,ContentResolver 中的增删改查方法都是不接收表名参数的,而是使用一个 Uri参数代替,这个参数被称为内容 URI。内容 URI给内容提供器中的数据建立了唯一标识符,它主要由两部分组成:

  1)权限(authority):用于对不同的应用程序做区分的,一般为了避免冲突,都会采用程序包名的方式来进行命名。比如某个程序的包名是 com.example.app,那么该程序对应的权限就可以命名为 com.example.app.provider;

  2)路径(path):用于对同一应用程序中不同的表做区分的,通常都会添加到权限的后面。比如某个程序的数据库里存在两张表,table1和 table2,这时就可以将路径分别命名为/table1和/table2。

  把权限和路径进行组合,内容 URI 就变成了 com.example.app.provider/table1和 com.example.app.provider/table2。不过,目前还很难辨认出这两个字符串就是两个内容URI,我们还需要在字符串的头部加上协议声明。因此,内容 URI最标准的格式写法如下:
  content://com.example.app.provider/table1
  content://com.example.app.provider/table2

  在得到了内容 URI字符串之后,我们还需要将它解析成 Uri 对象才可以作为参数传入。解析的方法也相当简单,代码如下所示:

Uri uri = Uri.parse("content://com.example.app.provider/table1")

  只需要调用 Uri.parse()方法,就可以将内容 URI字符串解析成 Uri 对象了。现在我们就可以使用这个 Uri对象来进行CRUD操作:

  (1)查询数据:

  若想查询table1 表中的数据,代码如下所示:

 Cursor cursor = getContentResolver().query(
uri, //指定查询某个应用程序下的某一张表
projection, //指定查询的列名
selection, //指定 where 的约束条件
selectionArgs, //为 where中的占位符提供具体的值
sortOrder //指定查询结果的排序方式
);

  查询完成后返回的仍然是一个 Cursor 对象,这时我们就可以将数据从 Cursor 对象中逐个读取出来了。 读取的思路仍然是通过移动游标的位置来遍历 Cursor 的所有行, 然后再取出每一行中相应列的数据,代码如下所示:

 if (cursor != null) {
while (cursor.moveToNext()) {
String column1 = cursor.getString(cursor.getColumnIndex("column1"));
int column2 = cursor.getInt(cursor.getColumnIndex("column2"));
}
cursor.close();
}

  (2)添加数据:

  将待添加的数据组装到 ContentValues 中,然后调用 ContentResolver的 insert()方法,将 Uri 和 ContentValues作为参数传入即可。

 ContentValues values = new ContentValues();
values.put("column1", "text");
values.put("column2", 1);
getContentResolver().insert(uri, values);

  (3)更新数据:
  如果我们想要更新这条新添加的数据,把 column1 的值清空,可以借助ContentResolver 的 update()方法实现,代码如下所示:

 ContentValues values = new ContentValues();
values.put("column1", "");
getContentResolver().update(uri, values, "column1 = ? and column2 = ?",new String[] {"text", "1"});

 (4)删除数据:

  我们可以调用 ContentResolver 的 delete()方法将刚才数据删除掉,代码如下所示:

 getContentResolver().delete(uri, "column2 = ?", new String[] { "1" });

  初步认识了CRUD操作后,我们来实践一下。

二、实践:读取联系人:

  先确保手机里有联系人,然后新建一个project:ContactsTest.

  (1)设置布局文件

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="@+id/contacts_view"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</LinearLayout>

  在LinearLayout 里我们放置了一个 ListView,用于显示联系人。

  (2)修改主活动代码:

 public class MainActivity extends AppCompatActivity {

     ListView contactsView;
ArrayAdapter<String> adapter;
List<String> contactsList = new ArrayList<String>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contactsView = (ListView) findViewById(R.id.contacts_view);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, contactsList);
contactsView.setAdapter(adapter);
readContacts();
}
private void readContacts() {
Cursor cursor = null;
try {
// 查询联系人数据
cursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, null, null, null);
while (cursor.moveToNext()) {
// 获取联系人姓名
String displayName = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
// 获取联系人手机号
String number = cursor.getString(cursor.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsList.add(displayName + "\n" + number);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (cursor != null) {
cursor.close();
}
}
}
}

  在 onCreate()方法中,我们首先获取了 ListView控件的实例,并给它设置好了适配器,然后就去调用 readContacts()方法。在readContacts()方法中,我们使用了 ContentResolver 的 query()方法来查询系统的联系人数据。 不过传入的 Uri参数显得有些奇怪,为什么没有调用 Uri.parse()方法去解析一个内容 URI 字符串呢?这是因为ContactsContract.CommonDataKinds.Phone类已经帮我们做好了封装, 提供了一个CONTENT_URI常量,这个常量就是使用 Uri.parse()方法解析后的结果。接着我们历遍 Cursor 对象读取数据,联系人姓名这一列对应常量为ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,联系人手机号这一列对应的常量是 ContactsContract.CommonDataKinds.Phone.NUMBER。两个数据都取出之后,将它们进行拼接,并且中间加上换行符,然后将拼接后的数据添加到 ListView 里。最后千万不要忘记将 Cursor 对象关闭掉。

  (3)修改权限:
  读取系统联系人也是需要声明权限的,因此修改AndroidManifest.xml 中的代码,如下所示:

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mycompany.contactstest" >
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" > <activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>

  现在便可以成功地运行程序了。

  //End.

Android学习笔记(十九)——内容提供器的更多相关文章

  1. 《第一行代码》学习笔记30-内容提供器Content Provider(3)

    1."如何在自己的程序中访问其他应用程序的数据",思路->获取到该应用程序的内容URI,再借助ContentResolver进行CRUD操作. 2.要实现跨程序共享数据-&g ...

  2. 《第一行代码》学习笔记28-内容提供器Content Provider(1)

    1.内容提供器:用于在不同的应用程序之间实现数据共享的功能,提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问 数据的安全性.使用内容提供器是Android实现跨程序共享数据 ...

  3. 《第一行代码》学习笔记29-内容提供器Content Provider(2)

    1.查询操作: if (cursor != null) { while (cusor.moveToNext()) { String column1 = cursor.getString(cursor. ...

  4. python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法

    python3.4学习笔记(十九) 同一台机器同时安装 python2.7 和 python3.4的解决方法 同一台机器同时安装 python2.7 和 python3.4不会冲突.安装在不同目录,然 ...

  5. Android入门(十四)内容提供器-实现跨程序共享实例

    原文链接:http://www.orlion.ga/661/ 打开SQLite博文中创建的 DatabaseDemo项目,首先将 MyDatabaseHelper中使用 Toast弹出创建数据库成功的 ...

  6. android笔记 : Content provider内容提供器

    内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能. 内容提供器的用法一般有两种,一种是使用现有的内容提供器来读取和操作相应程序中的数据,另一种是创建自己的内 ...

  7. 【转】Pro Android学习笔记(九八):BroadcastReceiver(2):接收器触发通知

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.sina.com.cn/flowingflying或作者@恺风Wei-傻瓜与非傻瓜 广播接 ...

  8. 【转】 Pro Android学习笔记(九二):AsyncTask(1):AsyncTask类

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在Handler的学习系列中,学习了如何h ...

  9. Android学习笔记(九)——布局和控件的自定义

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! View是 Android中一种最基本的 UI组件,它可以在屏幕上绘制一块矩形区域,并能响应这块区域的各种事件 ...

  10. 【转】Pro Android学习笔记(九):了解Content Provider(下下)

    Content provider作为信息的读出,比较常见的还有文件的读写,最基础的就是二进制文件的的读写,例如img文件,音频文件的读写.在数据库中存放了该文件的路径,我们可以通过ContentPro ...

随机推荐

  1. 查看apt-get安装软件的版本

    apt-cache search name 查询 apt-get install name 安装 dpkg dpkg dpkg-checkbuilddeps dpkg-genchanges dpkg- ...

  2. easyUI中tree的简单使用

    一.在JS中的代码 $('#tt').tree({ url: baseCtx + 'lib/easyui-1.4/demo/tree/tree_data1.json',//tree数据的来源,json ...

  3. (转)Java API设计清单

    转自: 伯乐在线 Java API设计清单 英文原文 TheAmiableAPI 在设计Java API的时候总是有很多不同的规范和考量.与任何复杂的事物一样,这项工作往往就是在考验我们思考的缜密程度 ...

  4. Tomcat web.xml中定义了文件扩展名到MIME类型的对应关系

    Tomcat在返回静态资源时,会根据资源文件的扩展名产生对应的content-type头(也即MIME类型)添加到response header中. 在Tomcat的web.xml规定了扩展名及相应M ...

  5. 60行JS实现俄罗斯方块

    参考文献:http://www.cnblogs.com/jimaojin/p/5413857.html 原版: <!doctype html><html><head> ...

  6. 欧几里德算法 GCD

    递归: int gcd(int a,int b) { ?a:gcd(b,a%b); } 非递归: int gcd(int m,int n) { int r; ) { m=n; n=r; } retur ...

  7. asp.net 中的app_offline.htm的使用

    前段时间,系统升级,由于系统更新发布时间较长,所以必须停掉站点进行更新.导致很多用户都来反馈系统无法访问,还认为站点被黑掉了. 所以经过那件事我们也在思考,如何做到不停机,进行热部署.单机环境下(双机 ...

  8. [Unity] Unity3D研究院编辑器之自定义默认资源的Inspector面板

    比如编辑模式下对场景或者特定文件夹有一些操作可以在这个面板里来完成.. 代码如下. using UnityEngine; using System.Collections; using UnityEd ...

  9. python抓取网站URL小工具

    1.安装Python requests模块(通过pip): 环境搭建好了! 2.测试一下抓取URL的过程: 抓取出来的URL有JavaScript代码,正则上还有待更加完善,有兴趣的可以研究下~! 工 ...

  10. SCWS分词扩展在WINDOWS下的安装方法

    安装之前先确认您是否拥有主机的安装权限,否则无法进行安装,安装步骤如下: 1. 根据您当前用的 PHP 版本,下载相应已编译好的 php_scws.dll 扩展库. 目前支持以下版本   [PHP-4 ...