如果一个 APP 使用内容提供器对其数据提供了对外访问的接口,那么任何其他的 APP 都可以访问这部分的数据啦,像 Android 中的电话簿、短信等程序都提供了类似的访问接口。

1 ContentResolver 基础

ContentResolver 中提供了一系列方法用于对数据进行 CRUD 操作:

方法 说明
insert() 添加数据。
update() 更新数据。
delete() 删除数据。
query() 查询数据。

这些方法使用 Uri 作为参数,它被称为内容 URI,它为数据建立了唯一标识符。内容 URI 由三部分组成:
* 协议声明 - content://
* authority - 使用程序包名来命名,用于区分不同的应用程序。
* path - 用于区分不同的表。

一个完整内容 URI 格式为:content:///

得到了内容 URI 字符串后,需要调用 Uri.parse() 方法把它解析为 Uri 对象就可以作为参数传入 ContentResolver 方法,代码如下:

Uri uri = Uri.parse("content://com.deniro.app.provider/tableName");Cursor cursor = getContentResolver().query(uri,projection,selection,selectionArgs,sortOrder);

1.1 查询

query 方法参数说明:

参数 说明 示例
uri 查询某个 APP 下的某一张表 from table_name
projection 指定表列名 select column1,column2
selection 指定 where 约束条件 where column = value
selectionArgs 为 selection 中的占位符提供具体的值 -
orderBy 指定排序方式 order by column1,column2

查询完成后会返回一个 Cursor 对象,读取逻辑是:通过移动游标来遍历 Cursor 中的所有行,然后再取出每一行中相应列的数据,代码如下:

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

1.2 新增

insert 方法定义如下:

 public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,                @Nullable ContentValues values) 

它还需要一个 ContentValues,作为需要新增的数据。

示例代码如下:

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

1.3 更新

update 方法定义如下:

public final int update(@RequiresPermission.Write @NonNull Uri uri,            @Nullable ContentValues values, @Nullable String where,            @Nullable String[] selectionArgs)

除了 uri 与 ContentValues ,update 方法还需要 where 条件约束的参数,来确定需要更新的数据范围。

示例代码如下:

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

1.4 删除

delete 方法定义如下:

public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable String where,            @Nullable String[] selectionArgs) 

delete 方法所需要的参数与 update 方法相同。

示例代码如下:

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

2 读取系统联系人信息

首先在模拟器中手工添加一些联系人信息,打开电话簿,点击 【ADD A CONTACT 】或者右下角的图标按钮:

第一次新增联系人时,会弹出【是否创建在线账号用于备份联系人信息】的选择框,这里我们选择 KEEP LOCAL:

然后输入联系人的姓名与手机号码:

接着,点击右上角的打勾按钮。

最后,以类似的方式再添加一个联系人:

现在,我们要开始使用内容提供器来读取系统联系人信息啦。

布局文件:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="net.deniro.android.contactstest.MainActivity">   <ListView       android:id="@+id/contacts"       android:layout_width="match_parent"       android:layout_height="match_parent">ListView>LinearLayout>

我们把读取到的系统联系人信息放在一个 ListView 中展示。

Activity:

package net.deniro.android.contactstest;import android.Manifest;import android.content.pm.PackageManager;import android.database.Cursor;import android.os.Bundle;import android.provider.ContactsContract;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.support.v7.app.AppCompatActivity;import android.widget.ArrayAdapter;import android.widget.ListView;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity {    List contacts = new ArrayList<>();    ArrayAdapter adapter = null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //设置 ListView 内容        ListView contactsView = (ListView) findViewById(R.id.contacts);        adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, contacts);        contactsView.setAdapter(adapter);        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {            //请求读取联系人的权限            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS}, 1);        } else {            readContacts();        }    }    private void readContacts() {        Cursor cursor = null;        try {            cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);            if (cursor != null) {                while (cursor.moveToNext()) {                    //联系人姓名                    String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));                    //手机号                    String mobile = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));                    contacts.add(name + ":" + mobile);                }                //通知 ListView 数据已更新                adapter.notifyDataSetChanged();            }        } catch (Exception e) {            e.printStackTrace();        } finally {            if (cursor != null) {                cursor.close();            }        }    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        switch (requestCode) {            case 1://获得权限后,读取联系人                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {                    readContacts();                } else {                    Toast.makeText(this, "被拒绝", Toast.LENGTH_SHORT).show();                }                break;            default:                throw new RuntimeException("onRequestPermissionsResult");        }    }}

这里使用了 ContentResolver 的 query() 方法来查询系统联系人的数据。ContactsContract.CommonDataKinds.Phone.CONTENT_URI 封装了内容 URI 字符串;接着,从 ContactsContract.CommonDataKinds.Phone 常量中,通过 Cursor 对象遍历获取联系人的姓名与手机号;然后通知 ListView 刷新列表。

因为读取系统联系人涉及到危险权限,所以这里先判断是否有权限。

最后记得在 AndroidManifest.xml 中声明权限:

<uses-permission android:name="android.permission.READ_CONTACTS"/>

为了示例的简洁,没有即时刷新联系人列表,所以如果有新增联系人,需要退出 APP 后再进入才会刷新联系人列表。

运行 APP:

是不是很简单呀O(∩_∩)O哈哈~

更多相关文章

  1. Android(安卓)中 startService()启动service的过程分析
  2. Android常用的数据结构
  3. Android(安卓)蓝牙BLE开发详解
  4. Android(安卓)Tab切换之Fragment方法
  5. Android视图绘制流程解析(二)
  6. Android(安卓)MediaPlayer和VideoView的使用
  7. Android退出整个应用的方法
  8. android第一次启动时Settings的默认值
  9. Android(安卓)ADB超简单的安装教程(推荐)

随机推荐

  1. Android柱状图-柱子分组
  2. Android资源目录
  3. 【笔记】android捕获触摸事件
  4. Android(安卓)获取设备宽高分辨率
  5. android Buton使用
  6. Android(安卓)Material Design 实践(六)-
  7. [Android] Android(安卓)监听WIFI
  8. Android(安卓)Initializing a Build Envi
  9. Unity调用Android语音合成
  10. Android(安卓)学习--ListView 的使用(二)