//此系列博文是《第一行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. (C/C++学习笔记) 十九. 模板

    十九. 模板 ● 模板的基本概念 模板(template) 函数模板:可以用来创建一个通用功能的函数,以支持多种不同形参,进一步简化重载函数的函数体设计. 语法: template <<模 ...

随机推荐

  1. 【bzoj4326】[NOIP2015]运输计划

    题目描述 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该 ...

  2. Android手机浏览器访问本地网络相关问题

    为了测试开发的手机网站,常常需要使手机直接访问本地网络. 在这个过程中碰到几个问题,记下来供以后参考 1. 在本地主机运行apache后,使用localhost和127.0.0.1可以访问页面,但使用 ...

  3. 常用的获取时间差的sql语句

    "select count(*) from [注册] where datediff(day,time,getdate())<1";//获取当天注册人员数 sql=" ...

  4. iOS: 悬浮的条件筛选框使用二

    一.介绍: 在前面已经介绍了一种条件悬浮框,使用的是tableView的Plain分组样式实现的,因为这是tableView本身就具备的功能,分组悬浮效果.这次我来介绍第二种更加简单的方法,采用两个S ...

  5. Quartz.NET快速上手第一课(官网文档翻译)

    Quartz.NET快速上手第一课(官网文档翻译) 原文链接 在你使用调度者(scheduler)之前,你需要对它进行实例化(谁能猜到这呢?).在实例化scheduler时候,你需要使用ISchedu ...

  6. 【转】Angular运行原理揭秘 Part 1

    当你用AngularJS写的应用越多, 你会越发的觉得它相当神奇. 之前我用AngularJS实现了相当多酷炫的效果, 所以我决定去看看它的源码, 我想这样也许我能知道它的原理. 下面是我从源码中找到 ...

  7. 3D案例,导航,导航升级版

    /*****************************百度钱包旋转变内容******************************/ <!DOCTYPE html> <htm ...

  8. xcode 必用插件二

    本文大致整理了自己用过的一些插件的使用感想(就是好不好用). 在那之前先简单贴两条插件须知,知道的可以忽略. 1.Alcatraz 类似于管理第三方库的cocoapods,管理插件也有个Alcatra ...

  9. 枚举N行N列的自然数列

    数据库环境:SQL SERVER 2005 现有一个需求,要枚举1-50个自然数,分10行5列展示.如图,

  10. 接私活,得有套好框架,.net快速开发神器

    同一家公司的同事,拿同样的工资,以前他在用肾机,我还在用诺记.吃饭的时候他是买单王,我在想这家伙应该没存什么钱吧.结果前段时间他买了个沃尔沃S60L,可我一套省城小三房的首付都还没凑齐. 他说他经常在 ...