ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

ContentProvider和ContentResolver演示

2021-12-22 17:05:03  阅读:176  来源: 互联网

标签:演示 Uri ContentResolver uri import android ContentProvider public FIRST


(1)概述

这里来模拟应用是如何访问ContentProvider,所以此处的ContentProvider也是自定义的,后通过ContentResolver来访问,具体源码可访问如下:

(2)部分源码

(A)ContentProvider

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.provider">

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <permission
        android:name="com.demo.contentProvider"
        android:label="provider permission"
        android:protectionLevel="normal" />

    <permission
        android:name="com.demo.contentProvider.read"
        android:label="provider read permission"
        android:protectionLevel="normal" />

    <permission
        android:name="com.demo.contentProvider.write"
        android:label="provider write permission"
        android:protectionLevel="normal" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Provider">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <provider
            android:name=".PersonContentProvider"
            android:authorities="com.example.provider"
            android:exported="true"
            android:enabled="true"
            android:grantUriPermissions="true"
            android:permission="com.demo.contentProvider"
            android:readPermission="com.demo.contentProvider.read"
            android:writePermission="com.demo.contentProvider.write" />
    </application>

</manifest>
package com.example.provider;

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

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.io.File;

public class PersonContentProvider extends ContentProvider {

    private static final UriMatcher sUriMatcher;
    private static final int MATCH_FIRST = 1;
    private static final int MATCH_SECOND = 2;
    public static final String AUTHORITY = "com.example.provider";
    public static final Uri CONTENT_URI_FIRST = Uri.parse("content://" + AUTHORITY +
            File.separator + DatabaseHelper.TABLE_FIRST_NAME);
    public static final Uri CONTENT_URI_SECOND = Uri.parse("content://" + AUTHORITY +
            File.separator + DatabaseHelper.TABLE_SECOND_NAME);

    public static final String CONTENT_FIRST_TYPE = "vnd.android.cursor.dir/demo.first";
    public static final String CONTENT_SECOND_TYPE = "vnd.android.cursor.item/demo.second";

    static {
        sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        sUriMatcher.addURI(AUTHORITY, DatabaseHelper.TABLE_FIRST_NAME, MATCH_FIRST);
        sUriMatcher.addURI(AUTHORITY, DatabaseHelper.TABLE_SECOND_NAME, MATCH_SECOND);
    }

    private DatabaseHelper mDbHelper;

    @Override
    public boolean onCreate() {
        mDbHelper = new DatabaseHelper(getContext());
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) {
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
        switch (sUriMatcher.match(uri)) {
            case MATCH_FIRST:
                queryBuilder.setTables(DatabaseHelper.TABLE_FIRST_NAME);
                break;
            case MATCH_SECOND:
                queryBuilder.setTables(DatabaseHelper.TABLE_SECOND_NAME);
                break;
            default:
                throw new IllegalArgumentException("Unknow URI: " + uri);
        }
        SQLiteDatabase db = mDbHelper.getReadableDatabase();
        Cursor cursor = queryBuilder.query(db, strings, s, strings1, null, null, null);
        return cursor;
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        switch (sUriMatcher.match(uri)) {
            case MATCH_FIRST: {
                return CONTENT_FIRST_TYPE;
            }
            case MATCH_SECOND: {
                return CONTENT_SECOND_TYPE;
            }
        }
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) {
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        Uri retUri = null;
        long rowID = 0;
        switch (sUriMatcher.match(uri)) {
            case MATCH_FIRST:
                rowID = db.insert(DatabaseHelper.TABLE_FIRST_NAME, null, contentValues);
                if (rowID > 0) {
                    retUri = ContentUris.withAppendedId(uri, rowID);
                }
                break;
            case MATCH_SECOND:
                rowID = db.insert(DatabaseHelper.TABLE_SECOND_NAME, null, contentValues);
                if (rowID > 0) {
                    retUri = ContentUris.withAppendedId(uri, rowID);
                }
                break;
            default:
                throw new IllegalArgumentException("Unknow URI: " + uri);
        }
        return retUri;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) {
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        int count = 0;
        switch (sUriMatcher.match(uri)) {
            case MATCH_FIRST:
                count = db.delete(DatabaseHelper.TABLE_FIRST_NAME, s, strings);
                break;

            case MATCH_SECOND:
                count = db.delete(DatabaseHelper.TABLE_SECOND_NAME, s, strings);
                break;
            default:
                throw new IllegalArgumentException("Unknow URI :" + uri);

        }
        this.getContext().getContentResolver().notifyChange(uri, null);
        return count;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) {
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        int count = 0;
        switch (sUriMatcher.match(uri)) {
            case MATCH_FIRST:
                count = db.update(DatabaseHelper.TABLE_FIRST_NAME, contentValues, s, strings);
                break;
            case MATCH_SECOND:
                count = db.update(DatabaseHelper.TABLE_SECOND_NAME, contentValues, s, strings);
                break;

            default:
                throw new IllegalArgumentException("Unknow URI : " + uri);
        }
        this.getContext().getContentResolver().notifyChange(uri, null);
        return count;
    }
}

(B)ContentResolver

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.resolver">

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

    <uses-permission android:name="com.demo.contentProvider.read" />
    <uses-permission android:name="com.demo.contentProvider.write" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Resolver">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="com.example.second"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:mimeType="vnd.android.cursor.item/demo.second" />
            </intent-filter>
        </activity>
    </application>

</manifest>
package com.example.resolver;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentValues;
import android.content.Intent;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final String TABLE_FIRST_NAME = "first";
    private static final String TABLE_SECOND_NAME = "second";
    public static final String AUTHORITY = "com.example.provider";
    public static final Uri CONTENT_URI_FIRST = Uri.parse("content://" + AUTHORITY + File.separator + TABLE_FIRST_NAME);
    public static final Uri CONTENT_URI_SECOND = Uri.parse("content://" + AUTHORITY + File.separator + TABLE_SECOND_NAME);
    
    public Uri mCurrentURI = getUri(TABLE_FIRST_NAME);

    private DataBaseObserver mObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        mObserver = new DataBaseObserver(new Handler());
        getContentResolver().registerContentObserver(getUri(null), true, mObserver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        getContentResolver().unregisterContentObserver(mObserver);
    }

    public class DataBaseObserver extends ContentObserver {

        public DataBaseObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            Log.e("MainActivity", "selfChange = " + selfChange);
        }
    }

    private Uri getUri(String path) {
        return new Uri.Builder().authority(AUTHORITY)
                .path(path)
                .scheme("content")
                .build();
    }

    private void secondPart() {
        Intent intent = new Intent();
        intent.setAction("com.example.second");
        intent.setData(mCurrentURI);
        try {
            startActivity(intent);
        } catch (Exception e) {
            Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }

    private void insert() {
        ContentValues values = new ContentValues();
        values.put("name", "hello");
        values.put("detail", "my name is demo");
        Uri uri = this.getContentResolver().insert(mCurrentURI, values);
        Log.e("MainActivity", "insert : " + uri.toString());
    }

    private void query() {
        Cursor cursor = this.getContentResolver().query(mCurrentURI, null, null, null, null);
        Log.e("MainActivity", "query : count = " + cursor.getCount());
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            String table = cursor.getString(cursor.getColumnIndex("table_name"));
            String name = cursor.getString(cursor.getColumnIndex("name"));
            String detail = cursor.getString(cursor.getColumnIndex("detail"));
            Log.e("MainActivity", "query : table_name = " + table + ", name = " + name + ", detail = " + detail);
            cursor.moveToNext();
        }
        cursor.close();
    }

    private void update() {
        ContentValues values = new ContentValues();
        values.put("detail", "my name is update");
        int count = this.getContentResolver().update(mCurrentURI, values, "_id = 1", null);
        Log.e("MainActivity", "update : count = " + count);
        query();
    }

    private void delete() {
        int count = this.getContentResolver().delete(mCurrentURI, "_id = 1", null);
        Log.e("MainActivity", "delete : count = " + count);
        query();
    }

    private void switchURI(Uri uri) {
        mCurrentURI = uri;
        mtv.setText("switch URI = " + mCurrentURI.toString());
    }
}

(3)注意事项

(A)Android R平台,将软件的TargetApi提升到30后,原来用的好好的自定义的ContentProvider找不到了,或者直接报 Unknow Uri 问题。

//需要在使用Uri的客户端的AndroidManifest.xml下加上标签

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

否则在进行registerContentObserver会出现如下Error:

getContentResolver().registerContentObserver(getUri(null), true, mObserver);

//error
Failed to find provider com.demo.provider.PersonContentProvider for user 0

(B)Provider权限问题

ContentProvider:

<permission
        android:name="com.demo.contentProvider"
        android:label="provider permission"
        android:protectionLevel="normal" />

    <permission
        android:name="com.demo.contentProvider.read"
        android:label="provider read permission"
        android:protectionLevel="normal" />

    <permission
        android:name="com.demo.contentProvider.write"
        android:label="provider write permission"
        android:protectionLevel="normal" />

<provider
            android:name=".PersonContentProvider"
            android:authorities="com.example.provider"
            android:exported="true"
            android:enabled="true"
            android:grantUriPermissions="true"
            android:permission="com.demo.contentProvider"
            android:readPermission="com.demo.contentProvider.read"
            android:writePermission="com.demo.contentProvider.write" />

ContentResolver:

<uses-permission android:name="com.demo.contentProvider.read" />
<uses-permission android:name="com.demo.contentProvider.write" />
  • exported:这个属性用于指示该服务是否能被其他程序应用组件调用或跟他交互; 取值为(true | false),如果设置成true,则能够被调用或交互,否则不能;
  • readPermission:使用Content Provider的查询功能所必需的权限,即使用ContentProvider里的query()函数的权限;
  • writePermission:使用ContentProvider的修改功能所必须的权限,即使用ContentProvider的insert()、update()、delete()函数的权限;
  • permission:客户端读、写 Content Provider 中的数据所必需的权限名称,readPermission和writePermission属性优先于本设置;

标签:演示,Uri,ContentResolver,uri,import,android,ContentProvider,public,FIRST
来源: https://blog.csdn.net/dongxianfei/article/details/122088208

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有