//此系列博文是《第一行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. C#------如何取出exe运行文件给客户使用

    1.将解决方案配置里面的“Debug”转换成“Release” 2.右击“解决方案”,选着“重新生成解决方案”,以得到最新的版本 3.找到工程目录下的“bin”文件夹,里面有“Release”文件夹, ...

  2. zabbix搭建

    首先创建zabbix组和用户 groupadd zabbix useradd -g zabbix zabbix mkdir -p /app/local/zabbix#然后创建zabbix编译安装目录 ...

  3. 10月23日上午PHP数组

    正则表达式 1.替换 $s = "hello5world"; $s = preg_replace("/\d/","#",$s); echo ...

  4. CodeForces 689B Mike and Shortcuts (BFS or 最短路)

    题目链接:http://codeforces.com/problemset/problem/689/B 题目大意: 留坑 明天中秋~

  5. ES6标准

    1. ES6标准感觉越来越向传统语言靠拢了,以后写到ES6的标准都记录下: ,,]; // =>操作符 array.forEach(v => console.log(v)); 是不是简化了 ...

  6. Unity逻辑热更新

    http://www.xuanyusong.com/archives/3075 http://www.unitymanual.com/thread-36503-1-1.html http://www. ...

  7. 【转】七年IT经验的七个总结

    http://www.unitymanual.com/thread-30000-1-1.html?_dsign=ebe6a043 1.分享第一条经验:“学历代表过去.能力代表现在.学习力代表未来.” ...

  8. 学海无涯的整理Ing..........

    1.文章:Understanding JavaScript Function Invocation and “this” http://yehudakatz.com/2011/08/11/unders ...

  9. Winform端上传图片到服务器

    转载自  在winform实现文件上传到服务器 webform上传文件可能大家都写过很多,一个HtmlInputFile.PostedFile.SaveAs就搞定了,不过不知道大家有没有在winfor ...

  10. Mysql InnoDB行锁实现方式(转)

    Mysql InnoDB行锁实现方式 InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的.InnoDB这种行锁实现特点 ...