Android——ContentProvider

概述

  • ContentProvider为App存取内部数据提供统一的外部接口,让不同的应用之间得以共享数据。
  • ContentProvider只是服务端App存取数据的抽象类,我们需要在其基础上实现一个完整 的内容提供器,并重写下列方法:

onCreate :创建数据库并获得数据库连接。
insert :插入数据。
delete :删除数据。
update :更新数据。
query :查询数据,并返回结果集的游标。
getType:获取内容提供器支持的数据类型。

  • Uri(通用资源标识符),代表数据操作的地址,每一个Cont entProvider 都会有唯一的地址。ContentProvider 使用的Uri 语法结构如下:

content://authority/data_path/id

**content://** :是通用前缀,表示该Uri用于ContentProvider定位资源。

**authority** :是授权者名称,用来确定具体由哪一个ContentProvider提供资源。因此 一般authority都由 类的小写全称组成,以保证唯一性。

**data_path** :是数据路径,用来确定请求的是哪个数据集。

**id**:是数据编号,用来请求单条数据。如果是多条这个字段忽略。

  • 利用ContentProvider只实现服务端App的数据封装,如果客户端App想访问对方的内部数据,就要通过内容解析器ContentResolver访问。

Serve 内容提供者

案例代码

java 复制代码
package com.example.cpserve.provider;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.util.Log;

import com.example.cpserve.database.UserDBHelper;

public class MyContentProvider extends ContentProvider {
    private UserDBHelper dbHelper;

    @Override
    public boolean onCreate() {
        dbHelper = UserDBHelper.getInstance(getContext());
        Log.d("MyContentProvider", "onCREATE");
        return false;
    }

    // content://com.example.cpserve.provider.MyContentProvider/user
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        db.insert(UserDBHelper.TABLE_NAME, null, values);
        return uri;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
        SQLiteDatabase db = dbHelper.getReadableDatabase();
        return db.query(UserDBHelper.TABLE_NAME, projection, selection, selectionArgs, sortOrder, null, null, null);

    }

    @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 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");
    }
}

Client 访问者

案例代码

java 复制代码
package com.example.cpclient;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class ContentWriteActivity extends AppCompatActivity {
    private TextView tv_content;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_content_write);
        tv_content = findViewById(R.id.tv_content);

        findViewById(R.id.btn_save).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ContentValues values = new ContentValues();
                // cpserve里的MyContentProvider在创建表时只写了一个name字段
                values.put("name", "张三");
                getContentResolver().insert(UserInfoContent.CONTENT_URI, values);
            }
        });

        findViewById(R.id.btn_read).setOnClickListener(new View.OnClickListener() {
            @SuppressLint("Range")
            @Override
            public void onClick(View view) {
                Cursor cursor = getContentResolver().query(UserInfoContent.CONTENT_URI, null, null, null, null, null);
                if (cursor != null) {
                    StringBuilder sb = new StringBuilder();

                    while (cursor.moveToNext()) {
                        sb.append(cursor.getString(cursor.getColumnIndex("name")));
                    }
                    tv_content.setText(sb);
                }
            }
        });
    }
}

在访问者(Client)的AndroidManifest.xml里需要加入如下代码

java 复制代码
    <!-- 出于安全考虑,Android11要求应用事先说明需要访问的其他软件包 -->
    <queries>
        <!-- 第一种写法 -->
        <!-- <package android:name="com.example.cpserve"/>-->
        <!-- 第二种写法 -->
        <provider android:authorities="com.example.cpserve.provider.MyContentProvider"/>
    </queries>
相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui