Android22--内容提供器ContentProvider

# Android22--内容提供器ContentProvider

标签: Android

创建时间:2016-9-24 09:56:47
更新时间:2018-1-2 23:23:44


undefined

ContentProvider(内容提供者)是Android四大组件中的最后一个。主要用途:

  • 我们想在自己的应用中访问别的应用,比如手机联系人、短信等;我们想对这些数据进行读取或者修改;
  • 我们自己的应用,想把自己的一些数据暴露出来,给其他的应用进行读取或操作。

那么对应的使用其实也是对应的:

  • 读取数据:使用ContentResolver根据URI读取数据;
  • 共享数据:实现ContentProvider类,同时注册一个URI。

至于数据,就不一定是数据库了,可能是文本文件、xml或者其它类型。

名词简介 #

1、Uri:这里指的是内容URI。内容URI给内容提供器中的数据建立了唯一标识符,它主要由两部分组成,权限(authority)和路径(path)。

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

路径则是用于对同一应用程序中不同的表做区分的,通常都会添加到权限的后面。

比如某个程序的数据库里存在两张表,table1和table2,这时就可以将路径分别命名为/table1/table2,然后把权限和路径进行组合,内容URI就变成了com.example.app.provider/table1com.example.app.provider/table2

不过,目前还很难辨认出这两个字符串就是两个内容URI,我们还需要在字符串的头部加上协议声明。因此,内容URI最标准的格式写法如下:

content://com.example.app.provider/table1
content://com.example.app.provider/table2

2、ContentResolver
对于每一个应用程序来说,如果想要访问内容提供器中共享的数据,就一定要借助ContentResolve类,可以通过Context中的getContentResolver()方法获取到该类的实例。ContentResolver中提供了一系列的方法用于对数据进行CRUD操作,其中insert()方法用于添加数据,update()方法用于更新数据,delete()方法用于删除数据,query()方法用于查询数据。

ContentResolver类使用说明:

Cursorcursor=getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);

uri: 指定查询某个应用程序下的某一张表;
projection:指定查询的列名(类似字段);
selection:指定where的约束条件;可以为null;
selectionArgs:为where中的占位符提供具体的值;可以为null;
orderBy:指定查询结果的排序方式。可以为null。

读取数据 #

读取系统短信 #

private void getMsgs(){
    Uri uri = Uri.parse("content://sms/");
    ContentResolver resolver = getContentResolver();
    //获取的是哪些列的信息
    Cursor cursor = resolver.query(uri, new String[]{"address","date","type","body"}, null, null, null);
    while(cursor.moveToNext())
    {
        String address = cursor.getString(0);
        String date = cursor.getString(1);
        String type = cursor.getString(2);
        String body = cursor.getString(3);
        System.out.println("地址:" + address);
        System.out.println("时间:" + date);
        System.out.println("类型:" + type);
        System.out.println("内容:" + body);
        System.out.println("======================");
    }
    cursor.close();
}

别忘了,往AndroidManifest.xml加入读取收件箱的权限:

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

读取手机联系人 #

private void getContacts(){
    //①查询raw_contacts表获得联系人的id
    ContentResolver resolver = getContentResolver();
    Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
    //查询联系人数据
    cursor = resolver.query(uri, null, null, null, null);
    while(cursor.moveToNext())
    {
        //获取联系人姓名,手机号码
        String cName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
        String cNum = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
        System.out.println("姓名:" + cName);
        System.out.println("号码:" + cNum);
        System.out.println("======================");
    }
    cursor.close();
}

别忘了加读联系人的权限:

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

查询指定电话的联系人信息 #

private void queryContact(String number){
        Uri uri = Uri.parse("content://com.android.contacts/data/phones/filter/" + number);
        ContentResolver resolver = getContentResolver();
        Cursor cursor = resolver.query(uri, new String[]{"display_name"}, null, null, null);
        if (cursor.moveToFirst()) {
            String name = cursor.getString(0);
            System.out.println(number + "对应的联系人名称:" + name);
        }
    cursor.close();
}

共享数据 #

监听ContentProvider的数据变化 #

我们可以通过ContentObserver监听ContentProvider的数据变化:
自定义类继承ContentObserver,重写onChange方法,然后调用getContentResolver().registerContentObserver()注册监听器。

方法原型:

public final void registerContentObserver(Uri uri, boolean notifyForDescendants, ContentObserver observer) {
	
}

其中notifyForDescendants设置为true即可。

(未完待续)

Build by Loppo 0.6.6