Android四大组件之内容提供者ContentProvider

1.内容提供者概述

1.1 内容提供者功能概述

**内容提供者(ContentProvider)**主要用于在不同的应用程序之间实现数据共享的功能。
为什么使用?
因为通过数据持久化, .db或者SP(SharedPreferences)中的数据仅限于被创建的应用所访问,无法做到应用程序间的数据交互和共享。内容提供者就相当于对外部提供了一个操作当前应用数据库表的API,通过UriMatcher匹配相应的uri,达到对数据库中不同表CRUD的操作

1.2 内容提供者使用场景

ContentProvider的使用场景多用于:

  • 微信/支付宝 读取手机的联系人/通讯录
  • 比如今日头条需要访问淘宝的内容,根据淘宝的用户访问习惯来给使用今日头条的用户推荐定向广告
    -比如 开发一个蓝牙电话,需要向手机的联系人这个应用拿到手机的所有联系人

2.自定义ContentProvider

2.1 自定义ContentProvider的步骤

需要知道,Android的四大组件都是需要在AndroidManifest.xml中注册的.
创建自定义ContentProvider时,可以借助AndroidStudio的new ->Other->ContentProvider.
在这里插入图片描述
在创建时,需要勾选权限:
在这里插入图片描述

  • Exported属性 表示允许外部程序访问该应用的ContentProvider
  • Enabled属性 表示是否启用这个内容提供器
    还有一个最关键的是 URI Authorities ,这是令牌,只有匹配上了,才有权限来操作数据库。外部应用如果想要操作当前app,必须通过设置uri,然后UserProvider类中的UriMathcer会匹配外部app传递过来的uri来查看是否有权限操作当前app中的数据。Authorities可以是多个,通过";"来进行分割。
    在创建ContentProvider之后,该项目的AndroidManifest.xml中就会有如下的代码:
<provider
            android:name=".MyContentProvider"
            android:authorities="com.hfad.providertest.provider"
            android:enabled="true"
            android:exported="true"></provider>

自定义的ContentProvider继承自ContentProvider,ContentProvider类中有6个抽象方法,在使用子类继承他的时候,需要将这6个方法全部重写。

public class MyProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        return false;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        return null;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        return null;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        return 0;
    }
}

这些方法的功能分别是:
1.onCreate()
初始化内容提供器的时候调用。通常会在这里完成对数据库的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败。注意,只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供器才会被初始化

2.query()
内容提供器中查询数据。使用uri参数来确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortorder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回。

3.insert()
内容提供器中添加一条数据。使用uri 参数来确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URI。

4.update()
更新内容提供器中已有的数据。使用uri参数来确定更新哪一张表中的数据,新数据保存在values参数中,selection和 selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回。

5.delete()

内容提供器中删除数据。使用uri参数来确定删除哪一张表中的数据,selection 和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。

6.getType()

根据传入的内容URI来返回相应的 MIME类型。

可以看到,几乎每一个方法都会带有Uri这个参数,这个参数也正是调用方–内容解析者ContentResolver的增删改查方法时传递过来。而现在,我们需要对传入的Uri参数进行解析,从中分析出 调用方 期望访问的表和数据。

ContentProvider的5个方法中的Uri参数,全是其他应用(调用方–内容解析者ContentResolver)请求获取某一信息时传递过来的。

2.2 自定义URI写法及使用

URI: 统一资源标识符(Uniform Resource Identifier), 它和URL(统一资源定位符)什么关系呢,其实URI和URL都可以标识web主机上的资源,但URL是一种具体的URI,它是URI的一个子集,它不仅唯一标识资源,而且还提供了定位该资源的信息。而URI是对资源的抽象,实际应用还是URI居多。
在这里插入图片描述

  • 主题名(Schema):ContentProvider的URI前缀(Android指定)
  • 授权信息(Authority):ContentProvider的唯一标识符
  • 表名(Path):ContentProvider指向数据库中的某个表明
  • 记录(ID):表中的某个记录(若无指定,则返回全部记录)

UriMatcher : 外部若想对当前应用进行访问,必须能够匹配UriMatcher中的URI。
主要涉及到两个主要方法:

  • UriMatcher.addURI(String authorities,String path,int code)
    authorities: 添加匹配规则,对应Manifest中的authorities
    path: 一般标识 表名 表示为table_name或者table_name\id
    code:当URI被匹配之后会返回后面的Match Code

  • UriMathcer.match(Uri uri):对第三方传递的uri进行匹配

2.3 调用方-ContentResovler请求数据共享

ContentResovler 内容解析者,通过它和内容提供者的对接,才可以去对内容提供者中的数据进行操纵。通过调用上下文对象中的方法getContentResolver( )获取ContentResovler对象,里面提供对内容提供者中数据库操作的API

ContentResovler 内容解析者 是其他的应用,而不是包含ContentProvider的原应用。

获取数据代码样例

//一般情况下,我们很少自己去写内容提供者,一般使用其他app的内容提供者,但通过
    // 手写内容提供者我们能更好地理解ContentProvider的内部原理,为接下来使用内容提供者
    // 奠定了基础
    ContentResolver contentResolver = getContentResolver();
    Uri uri = Uri.parse("content://cn.wjx.contentprovider/user");
    Cursor cursor = contentResolver.query(uri, null, null, null, null);
    while (cursor.moveToNext()) {
        String id = cursor.getString(0);
        String username = cursor.getString(1);
        String password = cursor.getString(3);
        Log.d(TAG, "user-->id:" + id + " username:" + username + " password:" + password);
    }

*插入数据代码样例

    ContentResolver contentResolver = getContentResolver();
    Uri uri = Uri.parse("content://cn.wjx.contentprovider/user");
    ContentValues values = new ContentValues();
    ContentValues cv = new ContentValues();
    cv.put(FIELD_USERNAME, "track");
    cv.put(FIELD_PASSWORD, "xcn");
    cv.put(FIELD_SEX, "female");
    cv.put(FIELD_AGE, 22);
    Uri insert = contentResolver.insert(uri, cv);
    Log.d(TAG, "uri:"+insert);

2.4 使用总结

我们当我们需要暴露数据给第三方使用时,就需要知道前面的内容提供者怎么写了。

如果是读取别人的内容提供者内容,就需要后面的知识了。

学习内容提供者的话,顺便也要把数据库的知识巩固一下。

内容提供者的使用场景比较少,能列举出来就那么几个了。我只有在蓝牙电话上使用过内容提供者,当然啦,在我们的平时开发中,如果做社交软件的话,也需要获取到用户的联系人列表

然后保存到后台去,向用户推荐对应的好友用户

3.应用

使用内容提供者的几个应用:

  1. 读取短信验证码 参考链接:https://blog.csdn.net/qq_42676548/article/details/115176324
  2. 获取联系人相应信息
  3. 获取日历事件,向日历中添加提醒事件

4 参考链接:

本文参考:

  1. https://www.sunofbeach.net/a/1247852001912500224
  2. https://www.sunofbeach.net/a/1186839898213076992
  3. 郭霖-第一行代码(第二版)
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值