【Android】ContentProvider

64 阅读4分钟

ContentProvider

参考资料

参考资料 官方文档

ContentProvider 和 SqliteDataBase

实现效果

【1】Content Provider + Sqlite Database 共享数据 【2】APP可以访问另一个APP的Provider

创建

Empty View Activity 在这里插入图片描述 在这里插入图片描述

创建ContentProvider

在这里插入图片描述 在这里插入图片描述

创建DatabaseHelper

创建表存储

package com.test.contentproviderexample;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

public class DatabaseHelper extends SQLiteOpenHelper {
    static final String DATABASE_NAME = "UserDB";
    static final String TABLE_NAME = "Users";
    static final int DATABASE_VERSION = 1;

    static final String CREATE_DB_TABLE = "CREATE TABLE " + TABLE_NAME
            + " (id INTEGER PRIMARY KEY AUTOINCREMENT, "
            + " name TEXT NOT NULL);";

    public DatabaseHelper(@Nullable Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_DB_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
    }
}

new 一个 database

@Override
    public boolean onCreate() {
        Context context = getContext();
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        db = databaseHelper.getWritableDatabase();
        return false;
    }

构建界面

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp"
            android:layout_marginBottom="70dp"
            android:fontFamily="sans-serif"
            android:text="@string/heading"
            android:textAlignment="center" />

        <EditText
            android:id="@+id/textName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginEnd="20dp"
            android:layout_marginBottom="40dp"
            android:autofillHints=""
            android:fontFamily="@font/"
            android:hint="@string/hint_text"
            android:inputType="text|textMultiLine"
            android:minHeight="48dp"
            android:textColorHint="#546E7A" />

        <Button
            android:id="@+id/insertButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginEnd="20dp"
            android:layout_marginBottom="20dp"
            android:background="#F44336"
            android:onClick="onClickAddDetails"
            android:text="@string/insertButtonText"
            android:textAlignment="center"
            android:textStyle="bold" />

        <Button
            android:id="@+id/loadButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginEnd="20dp"
            android:layout_marginBottom="20dp"
            android:background="#F44336"
            android:onClick="onClickShowDetail"
            android:text="@string/load_text"
            android:textAlignment="center"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/res"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginEnd="20dp"
            android:clickable="false"
            android:ems="10"
            android:fontFamily="sans-serif"
            android:textColor="@android:color/holo_green_dark"
            android:textSize="18sp"
            android:textStyle="bold" />

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

在这里插入图片描述

插入数据

定义URL

    static final String authorities = "com.contentprovider.example";
    static final String URL = "content://" + authorities + "/users";
    static final Uri CONTENT_URI = Uri.parse(URL);
    static final String name = "name";

在contentProvider中重写insert方法

    @Override
    public Uri insert(@NonNull Uri uri, ContentValues values) {
        final long rowId = db.insert(DatabaseHelper.TABLE_NAME, null, values);
        if (rowId > 0) {
            Uri _uri = ContentUris.withAppendedId(uri, rowId);
            Objects.requireNonNull(getContext()).getContentResolver().notifyChange(_uri, null);
            return _uri;
        }
        throw new SQLiteException("Failed to add a record into " + uri);
    }

在MainActivity.java中定义插入方法

    public void onClickAddDetails(View view) {
        EditText editText = findViewById(R.id.textName);
        String text = editText.getText().toString();
        ContentValues values = new ContentValues();
        values.put(MyContentProvider.name, text);
        getContentResolver().insert(MyContentProvider.CONTENT_URI, values);
        Toast.makeText(this, "insert text", Toast.LENGTH_LONG).show();
    }

测试插入数据

在这里插入图片描述 在这里插入图片描述 运行过程: 【1】DatabaseHelper 创建了数据库UserDB 【2】利用MyContentProvider重写insert方法 在这里插入图片描述 【3】MainActivity点击insert 在这里插入图片描述

查询数据

重写ContentProvider - query方法

@Override
    public Cursor query(@NonNull Uri uri, String[] prxojection, String selection,
                        String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
        builder.setTables(DatabaseHelper.TABLE_NAME);
        Cursor cursor = builder.query(db, prxojection, selection, selectionArgs, null, null, sortOrder);
        ContentResolver provider = Objects.requireNonNull(getContext()).getContentResolver();
        cursor.setNotificationUri(provider, uri);
        return cursor;
    }

定义MainActivity的查询方法

    public void onClickShowDetail(View view) {
        Cursor cursor = getContentResolver().query(MyContentProvider.CONTENT_URI, null, null, null, null);
        TextView res = findViewById(R.id.res);
        StringBuilder builder = new StringBuilder();
        if (cursor != null && cursor.moveToFirst()) {
            do {
                int iName = cursor.getColumnIndex(DatabaseHelper.COLUMN_NAME);
                int iId = cursor.getColumnIndex(DatabaseHelper.COLUMN_ID);
                String name = cursor.getString(iName);
                String id = cursor.getString(iId);
                builder.append("\n").append(id).append(" - ").append(name);
            } while (cursor.moveToNext());
        }
        res.setText(builder.toString());
    }

测试查询数据

在这里插入图片描述 在这里插入图片描述

共享数据

创建另一个应用,通过provider可以访问到之前创建的应用的数据

构建界面

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="338dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp"
            android:layout_marginBottom="70dp"
            android:fontFamily="sans-serif"
            android:text="@string/heading"
            android:textAlignment="center" />

        <Button
            android:id="@+id/loadButton"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginTop="10dp"
            android:layout_marginEnd="20dp"
            android:layout_marginBottom="20dp"
            android:background="#F44336"
            android:onClick="onClickShowDetails"
            android:text="@string/load_text"
            android:textAlignment="center"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/res"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginEnd="20dp"
            android:clickable="false"
            android:ems="10"
            android:fontFamily="sans-serif"
            android:textColor="@android:color/holo_green_dark"
            android:textSize="18sp"
            android:textStyle="bold" />

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

在这里插入图片描述

定义查询方法

复制之前定义的查询方法,但是在另一个新的应用中

public void onClickShowDetails(View view) {
        Cursor cursor = getContentResolver().query(CONTENT_URI, null, null, null, null);
        TextView res = findViewById(R.id.res);
        StringBuilder builder = new StringBuilder();
        if (cursor != null && cursor.moveToFirst()) {
            do {
                int iName = cursor.getColumnIndex(COLUMN_NAME);
                int iId = cursor.getColumnIndex(COLUMN_ID);
                String name = cursor.getString(iName);
                String id = cursor.getString(iId);
                builder.append("\n").append(id).append(" - ").append(name);
            } while (cursor.moveToNext());
        }
        res.setText(builder.toString());
    }

AndroidManifest定义queries

在AndroidMainifest.xml中添加

    <queries>
        <provider android:authorities="com.contentprovider.example"/>
    </queries>

authorities需要与之前定义的一致 获取的一方 在这里插入图片描述 之前定义的provider,提供的一方 在这里插入图片描述

运行测试

在这里插入图片描述 获取到另一个应用定义的contentProvider中的数据

相关概念

参考官方文档

URL格式

  • content:// 固定在前面
  • authority 中间是程序的授权标志
  • table 表名