《Android第一行代码》
内容提供器简介
内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能够保证被访问数据的安全性。目前,使用内容提供器是Android实现扩平台共享数据的标准方式。
不同文件储存和SharedPreferences储存中的两种全局可读写操作模式,内容提供器可以选择只对哪一部分数据进行共享,从而保证我们数据的安全性。
内容提供器主要有两种操作,一种是利用现有的内容提供器来读取和操作相应程序的数据,另一种是创建自己的内容提供器提供给其他程序使用。接下来我让我们学习这两种操作,本次我们先学习利用现有的内容提供器来读取和操作相应程序的数据的相应操作。
访问其他程序中的数据
当一个程序通过内容提供器对其数据提供了外部访问接口,任何其他程序就都可以对这部分数据进行访问。Android系统自带的电话簿、短信、媒体播放器等程序都提供了类似的访问接口,这就使得第三方程序可以允许充分利用这部分的数据来实现更好的功能。接下来我们就来看看怎么使用这部分数据。
ContentResolver 的基本用法
要使用其他程序提供的数据,就需要借助ContentResolver类,可以通过Context中的getContentResolver()方法获取到该类实例。ContentResolver中提供了一系列方法用于对数据的CRUD(增删改查)操作,其中insert()方法用于添加数据,update()方法用于更新数据,delete()方法用于删除数据,query()方法用于查询数据。这种操作类似于SQLiteDataBase的操作,但不同于SQLiteDataBase的是,ContentResolver中的增删改查操作不接收表明参数,而是接收一个Uri参数。这个参数被称为内容ERI。内容URI给内容提供器中的数据建立了唯一的标识,他主要是由两部分组成,权限(authority)和路径(path)。权限适用于对不同的应用程序作区分的,一般为了避免冲突,都会采用程序包名方式来进行命名。比如摸个程序的包名是com.example.app,那么该程序对应的权限就可以命名为 com.example.app.provider。路径则是用于对同一个应用程序中不同的表作区分的。比如你的应用程序有两张表table1、table2,那么内容URI就可以写成com.example.app.provider/table1和com.example.app.provider/table2。不过这样还不算是完整的内容URI,还需要加上我们的协议声明:
content://com.example.app.provider/table1
content://com.example.app.provider/table2
这样我们就表明了我们想访问哪个程序里面的哪一个表。有了内容URI之后我们还需要把它解析成Uri对象,这样我们就可以把Uri对象传入。
解析的方法非常简单,代码如下:
Uri uri = Uri.parse("content://com.example.app.provider/table1");
现在我们就可以使用这个Uri对象来查询table1中的数据了,代码如下:
Cursor cursor = getContentResolver().qurey(
uri,
projection,
selection,
selectionArgs,
sortOrder);
参数说明:
uri 指定查询某个应用的某张表
projection 指定查询的列名
selection 指定 where 的约束条件
selectionArgs 为 where 中的占位符提供具体的值
sortOrder 指定查询的排列方式
查询完成后返回一个Cursor对象,我们就可以将数据从Cursor对象中逐个读取出来。读取方式是通过移动游标的位置来遍历Cursor的所有行,然后在取出每一行相应的数据,代码如下:
if(cursor!=null){
while(cursor.moveToNext()){
String colum1 = corsor.getString(cursor.getColumnIndex("column1"));
int colum2 = corsor.getInt(cursor.getColumnIndex("column2"));
}
cursor.close();
}
掌握了最难的查询,我们再来看看怎么在表内添加一条数据:
ContentValues v = new ContentValues();
v.put("column1","newText");
v.put("column2",1);
getContentResolver().insert(uri,v);
可以看到,跟数据库的操作一样,我们依然是把数据封装在 ContentVakues 中,然后调用ContentResolver的insert()方法,将 Uri 和 ContentVakues 作为参数传入即可。
让我们再来看看数据的更新:
ContentValues v = new ContentValues();
v.put("column1","newText2");
v.put("column2",111);
getContentResolver().update(uri, "column1 = ? and column2 = ?", new String[]{"newText","1"});
然后是删除:
getContentResolver().delete(uri,"column2 = ?", new String[]{"1"});
以上就是ContentResolver对数据的增删改查,看到这里相信好多人会期待最后会有一个具体的示例来巩固刚才学到的知识,接下来我们就利用学到的知识来读取手机电话簿的联系人信系。
读取手机联系人信息
对于示例的UI界面我就不再多说了,相信大家都会。我写一个方法来获取手机联系人的信息,把获取到的联系人信息通过return一个List返回给调用者,一共我们需要做三件事。
- 新建一个联系人的Modle来映射我们的联系人信息
- 在AndroidManifest.xml中添加访问联系人的权限(安卓版本6.0以下)
- 编写我们的方法
- 假设我们想要拿到联系人的电话号和名称,我们就可以写这样一个简单的modle:
class Contact{
private String name;
private String num;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setNum(String num){
this.num = num;
}
public String getNum(){
return num;
}
}
- 因为我们需要读取手机联系人信息,所以我们需要在Androidmanifest.xml中添加读取联系人信息的权限:
<uses-permission android:name="android.permission.READ_CONTACTS" />
- 现在我们开始写我们的方法,思路是这样的:
因为我们需要利用Context来get我们的ContentResolver实例,所以这个方法需要一个Context参数,并且要有一个List返回值把我们拿到的信息返回给调用者。
public List<Contact> getContactDate(Context context){
List<Contact> list = new ArrayList<>();
Cursor c = null;
c = context.getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,null,null,null);
while(c.moveToNext){
Contact con = new Contact();
//添加联系人姓名
con.setName(c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)));
//添加联系人电话号
con.setNum(c.getString(c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NUMBER)));
list.add(con);
}
return list;
}
到这里我们就把我们的工具方法写好了,当我们需要获取系人信息的时候,直接调用这个方法就能拿到手机电话簿中所有联系人的姓名和电话了。
本篇到此结束。