内容提供者、内容解析者和内容观察者

时间:2022-10-01 09:18:37

内容提供者、内容解析者和内容观察者

一、Linux文件权限

  1. Linxu下的用户分

    • u所有者
    • g所属组
    • o其他用户
  2. Linux下文件权限

    • r读
    • w写
    • x执行
  3. 文件权限表示

    • 文件类型(1位)+所有者权限(3位)+所属组权限(3位)+其他用户权限(3位),如图:

      内容提供者、内容解析者和内容观察者

      文件 权限 说明
      d lrwxrwxrwx l表示是链接,链接到sys/kernel/debug,所有者、所属组和其他用户都有读写执行权限
      data drwxrwx–x d表示是一个文件夹,rwx表示所有者具有读写执行权限,第二个rwx表示所属组具有读写执行权限,第三个–x表示其他用户只有执行权限
      default.prop -rw-r–r– -表示是一个文件,rw-表示所有者具有读写权限,r–表示所属组和其他用户都只具备读权限
  4. 默认地,每一个应用程序被分配一个唯一的Linux用户ID和组ID。通过设置权限许可,应用程序的文件只对该用户可见,只对应用程序本身可见。

  5. 文件权限的存在,保证了数据的安全性。当我们要读取数据时就需要具备相应的读写权限。比如当另一个应用想要获取短信应用的就需要在清单文件里添加相应的权限。底层是使用了Binder机制匿名共享内存

  6. 文件权限的存在,保证了数据的安全性。当我们要读取数据时就需要具备相应的读写权限。比如当另一个应用想要获取短信应用的就需要在清单文件里添加相应的权限。
    内容提供者、内容解析者和内容观察者

二、内容提供者(ContentProvider)

1. 作用

暴露本应用的私有数据,供其它应用使用。通过继承ContentProvider,有选择地暴露插入、删除、修改和查询本应用数据的接口。

2. 使用

  1. 继承ContentProvider抽象类,并选择性地重新增删改查方法

  2. 需要在清单文件中配置

    <application ...>
    <provider android:name="com.example.provider.SMSProvider"
    android:authorities="mysms"></provider>
    ...
    </application>
  3. 设置Uri(资源索引)并静态初始化UriMatcher帮助进行Uri匹配

    • Uri格式
      • Uri=schema://authorites/path/id
      • content://包名.数据库/表名/字段id
    • UriMatcher 的方法
        /**
    * 功能:Creates the root node of the URI tree.(创建URI树的根节点)
    * 参数code: the code to match for the root URI(匹配根URI的码)
    */

    UriMatcher(int code);
    /**
    *功能:Add a URI to match, and the code to return when this URI is matched.(添加一个uri用于匹配,并当匹配时返回设置的code)
    * 参数authority: 要匹配的authority
    * 参数path: 要匹配的path。*表示匹配任意文本,#表示匹配数字
    * 参数code: 当uri与给定的匹配时的返回值,必须是正数
    */

    addURI(String authority, String path, int code) ;
    /**
    *功能:Try to match against the path in a url.(尝试去匹配url中的路径)
    * uri:要进行匹配的uri
    * 返回值:int,匹配时返回预设的code;不匹配时返回-1
    */

    match(Uri uri);
  4. 重写增删查改方法(以查询为例)

    /**
    * 功能:处理客户端的请求
    * 参数uri:要查询的uri
    * 参数projection:要查询的字段集合
    * 参数selection:from语句
    * 参数selectionArgs:from语句的参数
    * 参数sortOrder:orderby语句
    * 返回值:Cursor,结果集的游标
    */

    query(Uri uri, String[] projection, String selection,
    String[] selectionArgs, String sortOrder)
  5. 在方法中进行Uri匹配,匹配时才执行增删查改

三、内容解析者(ContentResolver)

1. 作用

访问内容提供者,并解析返回的数据

2. 使用

  1. 通过上下文对象获取内容解析者

    ContentResolver resolver = this.getContentResolver();
  2. 发出增删查改请求

    Cursor cursor = resolver.query(Uri uri, String[] projection,
    String selection, String[] selectionArgs, String sortOrder);
  3. 解析cursor获取数据

    • 当uri不匹配时,cursor会为null,需要捕获异常;
    • cursor.getCount() > 0时才有必要进一步获取数据;
    • 在finally中关闭cursor,并注意进行cursor非空判断。

3. 实例:读取系统短信

  1. 短信数据库
    /data/data/com.android.providers.telephony/database/mmssms.db

  2. sms表中常用字段说明

    • type:表示发送还是接收,2表示发送,1表示接收,6表示正在发送中
    • data:时间的毫秒值
    • person:联系人姓名(陌生人为null)
    • address:发送或接收到号码
    • body:发送或接收的内容
    • read:是否阅读
  3. 相关协议

    • content://sms/inbox 收件箱
    • content://sms/sent 已发送
    • content://sms/draft 草稿
    • content://sms/outbox 发件箱
    • content://sms/failed 发送失败
    • content://sms/queued 待发送列表

四、内容观察者(ContentObserver)

1. 作用

配合内容解析者,实时监听内容提供者共享的数据是否发生变化

通知机制:handler机制

2. 使用

2.1 内容提供者方

  1. 获取内容解析器并通过观察者的url通知观察者改变的发生

    ContentResolver cr = getContext().getContentResolver();
    cr.notifyChange(uri, null);//注意:即使观察者不在运行状态,通过这个方法可以唤醒观察者
  2. 实例:系统自带的短信提供者(SmsProvider)

    public class SmsProvider extends ContentProvider{
    ...
    @Override
    public Uri insert(Uri url, ContentValues initialValues) {

    if (rowID > 0) {
    Uri uri = Uri.parse("content://" + table + "/" + rowID);

    if (Log.isLoggable(TAG, Log.VERBOSE)) {
    Log.d(TAG, "insert " + uri + " succeeded");
    }
    notifyChange(uri);
    return uri;
    } else {
    Log.e(TAG,"insert: failed! " + values.toString());
    }

    return null;
    }
    ...
    private void notifyChange(Uri uri) {
    ContentResolver cr = getContext().getContentResolver();
    cr.notifyChange(uri, null);
    cr.notifyChange(MmsSms.CONTENT_URI, null);
    cr.notifyChange(Uri.parse("content://mms-sms/conversations/"), null);
    }
    ...
    }

2.2 内容观察者方

  1. 获取内容解析器并注册观察者

     /**
    * 功能:ContentResolver的方法,注册一个ContentObserver,当指定uri数据改变时会回调给observer
    * 参数uri:要监听的uri
    * 参数notifyForDescendents:为false 表示精确匹配,即只匹配该Uri,为true 表示可以同时匹配其派生的Uri
    * 参数observer:ContentObserver派生的监听器实例
    */

    public final void registerContentObserver(Uri uri,
    boolean notifyForDescendents,
    ContentObserver observer)
    ContentResolver resovler = getContentResolver();
    Uri uri = Uri.parse("content://com.example.db/table");
    resovler.registerContentObserver(uri, false, new MyObserver(new Handler()));
  2. 写ContentObserver派生的监听器实例并重写onChange方法,当得知改变将执行里面的代码

    private class MyObserver extends ContentObserver {

    public MyObserver(Handler handler) {
    super(handler);
    }

    @Override
    public void onChange(boolean selfChange) {
    System.out.println("我是观察者,我观察到了内容的变化....");
    super.onChange(selfChange);
    }
    }

练习:

  • 做一个短信监控器
  • 做一个相对完整的短信应用