创建自己的内容提供器

如果想要实现跨程序共享数据的功能,官方推荐的方式就是使用内容提供器,可以通过新建一个类去继承ContentProvider的方式来创建一个自己的内容提供器。ContentProvider类中有6个抽象方法,我们在使用子类继承它的时候,需要将这6个方法全部重写。新建MyProvider继承自ContentProvider,代码如下所示:

package com.example.administrator.contactstest;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;

public class MyProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        return false;
    }
    
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        return null;
    }


    @Override
    public String getType(Uri uri) {
        return null;
    }


    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

1.onCreate():初始化内容提供器的时候调用。通常会在这里完成对数据的创建和升级等操作,返回true表示内容提供器初始化成功,返回false则表示失败。

2.query():从内容提供器中查询数据。使用uri参数来确定查询哪张表,projection参数用于确定查询哪些列,selection和selectionArgs参数用于约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中返回。

3.insert():向内容提供器中添加一条数据。使用uri参数来确定要添加到的表,待添加的数据保存在values参数中。添加完成后,返回一个用于表示这条新记录的URL。

4.update():更新内容提供器中已有的数据。使用uri参数来确定更新哪一张表中的数据,新数据保存在values参数中,selection和selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回。

5.delete():从内容提供器中删除数据。使用uri参数来确定删除哪一张表中的数据,selection和selectionArgs参数用于约束删除哪行,被删除的行将作为返回值返回。

6.getType():

根据传入的内容URI来返回相应的MIME类型。

 

匹配任意表的内容URI格式:

content://com.example.app.provider/*

匹配table表中的任意一行数据的内容URI格式:

content://com.example.app.provider/table/#

我们需要使用UriMatcher类来实现匹配内容URI的功能,UriMatcher类中提供了一个addURI()方法,这个方法接收3个参数,可以分别把authority、path和自定义int类型标识符传进去。这样,当调用UriMatcher的match()方法时,就可以将一个uri对象传入,返回值是某个可以匹配这个uri对象所对应的int类型标识符(也就是addURI()方法中的第三个参数),利用该int类型标识符,我们就可以判断出调用方期望访问的是哪张表中的数据了。

修改MainActivity.java代码:

package com.example.administrator.contactstest;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;

public class MyProvider extends ContentProvider {

    public static final int TABLE1_DIR = 0;//table1表中的所有数据

    public static final int TABLE1_ITEM = 1;//table1表中的单条数据

    public static final int TABLE2_DIR = 2;//table2表中的所有数据

    public static final int TABLE2_ITEM = 3;//table2表中的单条数据

    public static UriMatcher uriMatcher;//声明uri匹配类对象


    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);//实例化uri匹配类对象
        //向UriMatcher中添加内容URI
        uriMatcher.addURI("com.example.app.provider", "table1", TABLE1_DIR);
        uriMatcher.addURI("com.example.app.provider", "table1/#", TABLE1_ITEM);
        uriMatcher.addURI("com.example.app.provider", "table2", TABLE2_DIR);
        uriMatcher.addURI("com.example.app.provider", "table2/#", TABLE2_ITEM);
    }


    @Override
    public boolean onCreate() {
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        switch (uriMatcher.match(uri)) {
            case TABLE1_DIR:
                //查询table1表中的所有数据
                break;
            case TABLE1_ITEM:
                //查询table1表中的单条数据
                break;
            case TABLE2_DIR:
                //查询table2表中的所有数据
                break;
            case TABLE2_ITEM:
                //查询table2表中的单条数据
                break;
            default:
                break;
        }
        return null;
    }


        return null;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

这里再讲一下getType()方法,它是所有的内容提供器都必须提供的一个方法,用于获取Uri对象所对应的MIME类型。一个内容URI所对应的MIME字符串主要由3部分组成,Android对这3部分做了如下格式规定:

1.必须以vnd开头

2.如果内容URI以路径结尾,则在vnd后面加上android.cursor.dir/,如果以id结尾,则在vnd后面加上android.cursor.item/

3.最后接上vnd.<authority>.<path>

所以,对于content://com.example.app.provider/table1这个内容URI,它所对应的MIME类型就可以写成:

vnd.android.cursor.dir/vnd.com.example.app.provider.table1

对于content://com.example.app.provider/table1/1这个内容URI,它所对应的MIME类型就可以写成:

vnd.android.cursor.item/vnd.com.example.app.provider.table1

ManiActivity.java代码:

package com.example.administrator.contactstest;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;

public class MyProvider extends ContentProvider {

    public static final int TABLE1_DIR = 0;//table1表中的所有数据

    public static final int TABLE1_ITEM = 1;//table1表中的单条数据

    public static final int TABLE2_DIR = 2;//table2表中的所有数据

    public static final int TABLE2_ITEM = 3;//table2表中的单条数据

    public static UriMatcher uriMatcher;//声明uri匹配类对象


    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);//实例化uri匹配类对象
        //向UriMatcher中添加内容URI
        uriMatcher.addURI("com.example.app.provider", "table1", TABLE1_DIR);
        uriMatcher.addURI("com.example.app.provider", "table1/#", TABLE1_ITEM);
        uriMatcher.addURI("com.example.app.provider", "table2", TABLE2_DIR);
        uriMatcher.addURI("com.example.app.provider", "table2/#", TABLE2_ITEM);
    }


    @Override
    public boolean onCreate() {
        return false;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        switch (uriMatcher.match(uri)) {
            case TABLE1_DIR:
                //查询table1表中的所有数据
                break;
            case TABLE1_ITEM:
                //查询table1表中的单条数据
                break;
            case TABLE2_DIR:
                //查询table2表中的所有数据
                break;
            case TABLE2_ITEM:
                //查询table2表中的单条数据
                break;
            default:
                break;
        }
        return null;
    }

    @Override
    public String getType(Uri uri) {
        switch (uriMatcher.match(uri)) {
            case TABLE1_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.app.provider.table1";
            case TABLE1_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.app.provider.table1";
            case TABLE2_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.app.provider.table2";
            case TABLE2_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.app.provider.table2";
            default:
                break;
        }
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

到这里,一个完整的内容提供器就创建成功了,现在任何一个应用程序都可以使用ContentResolver来访问我们程序中的数据。那么前面所提到的,如何才能保证隐私数据不会泄露出去呢?其实多亏了内容提供器的良好机制,这个问题在不知不觉中被解决了。因为所有的CRUD操作都需要匹配到相应的内容URI,而这些内容URI都是需要我们自主的往UriMatcher中添加的,我们当然不会主动将一些隐私数据的URI添加到UriMatcher中,所以隐私的数据外界是无法访问到的。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值