Android基础知识——探究内容提供器
发布日期:2021-05-19 15:52:50 浏览次数:19 分类:精选文章

本文共 5303 字,大约阅读时间需要 17 分钟。

内容提供器与权限管理

内容提供器简介

内容提供器(ContentProvider)是一项强大的功能,用于在不同应用程序之间实现数据共享。在 Android 系统中,每个应用程序都可以通过内容提供器来提供数据给其他应用程序访问,同时也可以通过内容提供器来访问其他应用程序的数据。与 SharedPreferences 或文件存储等方式相比,内容提供器更具灵活性。你可以选择仅共享部分数据,从而有效保护隐私。


运行时权限

在 Android 中,所有权限都分为两类:普通权限和危险权限。普通权限可以在 AndroidManifest.xml 中直接声明,而危险权限需要在运行时申请。在使用危险权限时,开发者需要通过 ContextCompat.checkSelfPermission() 方法判断权限状态,符合条件时再调用 RequestPermissions() 方法进行权限申请。系统会跳出权限申请框 TextInput; 用户可以选择同意或拒绝,无论选择哪一方,最终都会通过 onRequestPermissionsResult() 方法进行处理。

以下是拨打电话权限的典型申请流程:

  • 在 AndroidManifest.xml 文件中添加权限声明。
  • 调用 checkSelfPermission() 方法判断当前权限状态。
  • 如果未授予权限,调用 requestPermissions() 方法 initiation。
  • 重写 onRequestPermissionsResult() 方法,处理用户的选择结果。

  • 访问其他程序中的数据

    使用 ContentResolver 进行操作

    使用 content resolver 可以访问其他应用程序的数据库。你需要调用 getContentResolver() 方法获取 content resolver 实例。与操作本应用程序数据库类似,通过 URI identifier 调用 CRUD 方法(增删改查)。以下是常见操作的示例:

    • 插入数据

      ContentValues values = new ContentValues();values.put("column1", "text");resolver.insert(uri, values);
    • 修改数据

      ContentValues values = new ContentValues();values.put("column1", "");resolver.update(uri, values, "id = ?", new String[]{"1"});
    • 删除数据

      resolver.delete(uri, "id = ?", new String[]{"1"});
    • 查询数据

      Cursor cursor = resolver.query(uri, null, null, null, null);

    访问联系人数据

    进行联系人数据的读取操作需要 READ_CONTACTS 权限。以下是实现这一功能的大致流程:

  • 检查权限状态,未授予时申请权限。
  • 使用 ContentResolver 调用 query() 方法,指定 ContactsContract.CommonDataKinds.Phone.CONTENT_URI URI。
  • 遍历数据库cursor,获取联系人信息并展示在列表视图上。

  • 创建自己的内容提供器

    要让其他应用程序能够访问你程序中的数据,你需要创建自己的内容提供器类。该类需继承 ContentProvider 并实现其六个抽象方法。以下是一个简单的实现示例:

    MyProvider 类

    public class MyProvider extends ContentProvider {    private static final int TABLE_DIR = 0;    private static final int TABLE_ITEM = 1;    private static UriMatcher matcher;    private static MySQLiteOpenHelper helper;    static {        matcher = new UriMatcher(UriMatcher.NO_MATCH);        matcher.addURI("com.example.temp.provider", "table", TABLE_DIR);        matcher.addURI("com.example.temp.provider", "table/#", TABLE_ITEM);    }    @Override    public boolean onCreate() {        sqliteOpenHelper = new MySQLiteOpenHelper(getContext(), "BookStore.db", null, 1);        return true;    }    @Override    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {        SQLiteDatabase database = helper.getReadableDatabase();        Cursor cursor = null;        switch (matcher.match(uri)) {            case TABLE_DIR:                cursor = database.query("Book", projection, selection, selectionArgs, null, null, sortOrder);                break;            case TABLE_ITEM:                String bookId = uri.getPathSegments().get(1);                cursor = database.query("Book", projection, "id = ?", new String[]{bookId}, null, null, sortOrder);                break;            default:                cursor = null;        }        return cursor;    }    @Override    public String getType(Uri uri) {        switch (matcher(matcher uri)) {            case TABLE_DIR:                return "vnd.android.cursor.dir/vnd.com.example.temp.provider.book";            case TABLE_ITEM:                return "vnd.android.cursor.item/vnd.com.example.temp.provider.book";        }        return null;    }    @Override    public Uri insert(Uri uri, ContentValues values) {        SQLiteDatabase database = helper.getWritableDatabase();        Uri mUri = null;        switch (matcher.match(uri)) {            case TABLE_DIR:            case TABLE_ITEM:                long newBookId = database.insert("Book", null, values);                mUri = Uri.parse("content://" + "com.example.temp.provider" + "/book/" + newBookId);                break;        }        return mUri;    }    @Override    public int delete(Uri uri, String selection, String[] selectionArgs) {        SQLiteDatabase database = helper.getWritableDatabase();        int returnRows = 0;        switch (matcher.match(uri)) {            case TABLE_DIR:                returnRows = database.delete("Book", selection, selectionArgs);                break;            case TABLE_ITEM:                String bookId = uri.getPathSegments().get(1);                returnRows = database.delete("Book", "id = ?", new String[]{bookId});                break;            default:                break;        }        return returnRows;    }    @Override    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {        SQLiteDatabase database = helper.getWritableDatabase();        int returnRows = 0;        switch (matcher.match(uri)) {            case TABLE_DIR:                returnRows = database.update("Book", values, selection, selectionArgs);                break;            case TABLE_ITEM:                String bookId = uri.getPathSegments().get(1);                returnRows = database.update("Book", values, "id = ?", new String[]{bookId});                break;            default:                break;        }        return returnRows;    }}

    在 AndroidManifest.xml 中注册内容提供器


    补充知识

    ContentProvider、ContentResolver、ContentObserver 之间的关系

    • ContentProvider

      • 提供数据给其他应用程序,作为内容的来源。
      • 实现多个应用之间的数据共享。
    • ContentResolver

      • 数据库操作工具,用于调用 ContentProvider 提供的数据。
      • 提供数据查询和通知功能。
    • ContentObserver

      • 数据变化监听器,用于追踪特定 URI 的数据状态变化。
      • 允许开发者在数据变化时执行自定义操作,类似数据库触发器。

    ContentProvider 是各个应用程序之间的中间人,它并不直接操作数据库或文件,仅仅实现数据接口。通过 ContentResolver 操作别人应用的数据时,需要先获取相应的权限。

    上一篇:Android基础知识——使用网络技术
    下一篇:Android基础知识——数据存储方案

    发表评论

    最新留言

    哈哈,博客排版真的漂亮呢~
    [***.90.31.176]2025年04月30日 14时58分45秒