内容提供者的简单使用

本文介绍了如何使用ContentProvider在Android应用间共享数据,包括何时使用ContentProvider、如何创建服务端和服务端的ContentProvider实现,以及客户端如何访问数据。还提到了权限管理和AndroidManifest.xml中的配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内容提供者的简单使用

最近在复习ContentProvider时遇到了一些问题,几经波折,终于解决了,故写下这篇博客,希望能帮到有相同问题的兄弟。

何时使用

当我们想要一个应用的数据向外部公开时,ContentProvider是一个不错的选择

怎么使用

我把两个应用分别叫做client和service,client是我的需要请求其他数据的应用,service是提供数据的应用

先生成service

需要生成ContentProvider的子类

public class MyProvider extends ContentProvider {
    public MyProvider() {
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // Implement this to handle requests to delete one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public String getType(Uri uri) {
        // TODO: Implement this to handle requests for the MIME type of the data
        // at the given URI.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO: Implement this to handle requests to insert a new row.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public boolean onCreate() {
        // TODO: Implement this to initialize your content provider on startup.
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        // TODO: Implement this to handle query requests from clients.
        return getContext().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);

    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
                      String[] selectionArgs) {
        // TODO: Implement this to handle requests to update one or more rows.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

里面都是一些默认方法,只是重写了query这个查询方法。内容提供器属于四大组件之一,使用时要先声明

<application>
    <provider
        android:name=".MyProvider"
        android:authorities="com.example.myprivider.provider"
        android:enabled="true"
        android:exported="true" />
</application>

这里的重点是authorities属性,他表明外部应该通过com.example.myprivider.provider来访问我们的ContentProvider,格式默认是包名.provider,同时也要enabled启动ContentProvider和exported允许外部访问

由于query方法访问我们的手机通讯录,我们在使用时先添加权限

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

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

</manifest>

代码请求权限

requestPermission(this, Manifest.permission.READ_CONTACTS);

public static void requestPermission(Activity activity, String permission) {
    if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(activity, new String[]{permission}, 1);
    }
}

这样我们的service应用就写好了。

写出client应用来访问数据

这个代码比较简单

Uri uri = Uri.parse("content://com.example.myprivider.provider");
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
   StringBuilder sb = new StringBuilder();
   do {
       @SuppressLint("Range") String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
       @SuppressLint("Range") String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
       sb.append(name).append(", ").append(number).append("\n");
   } while (cursor.moveToNext());
   binding.textView.setText(sb);
}

观察一下,uri比较重要,他是我们访问ContentProvider的重要角色,一般格式是content://访问的包名.provider/表名/序号。访问的包名.provider并不是绝对的,和我们的authorities属性(已加粗,往上找)有关,建议直接复制。其中表名和序号可有可无,具体看service中ContentProvider的实现,一般用来做一下标记,方便知道查询的是哪张表。
我们写完之后,还是不能直接访问,高版本的sdk要求我们必须提前声明要查询哪一个ContentProvider

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <queries>
        <package android:name="com.example.myprivider" />
    </queries>
</manifest >

这里的包名就是我们service的包名了

做完之后,先启动我们的service,申请访问权限,在启动client,就可以通过ContentProvider间接访问到通讯录了。

使用总结

1.ContentProvider一般配合SQLiteOpenHelper组合使用,db的query方法也是生成Cursor类,可以直接被ContentProvider返回
2.service应用一定要先启动
3.剩下的看评论区问题,再补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值