Android-ContentProvider详解

1 内容提供器简介

Content Provider 主要用于在不同应用程序间实现数据共享。
不同于文件存储和SharedPreferences存储中的两种全局可读写操作模式,Content Provider可以选择只对那一部分数据进行共享,从而保证我们的程序中的隐私数据不会由泄露的风险。

2 运行时权限

2.1 权限分类

危险权限9组24项需要进行运行时权限处理。

权限组名权限名
CALENDARREAD_CALENAR
WRITE_CALENDAR
CAMERACAMERA
CONTACTSREAD_CONTACETS
WRITE_CONTACTS
GET_ACCOUNTS
LOCATIONACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
MICROPHONERECORD_AUDIO
PHONEREAD_PHONE_STATE
CALL_PHONE
READ_CALL_LOG
WRITE_CALL_LOG
ADD_VOICEMAIL
USE_SIP
PROCESS_OUTGOING_CALLS
SENSORSBODY_SENSORS
SMSSEND_SMS
RECEIVE_SMS
READ_SMS
RECEIVE_WAP_PUSH
RECEIVE_MMS
STORAGEREAD_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE

普通权限,只需要在AndroidManifest.xml文件中添加权限声明就可以了。

2.2 在程序运行时申请权限

举例,申请打电话权限 Manifest.permission.CALL_PHONE
1.先进行判断是否已经获得权限,有则直接打电话,无则申请权限

ContextCompat.checkSelfPermission(MainActivity.this, Manifest.
			permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED

2.申请权限

ActivityCompat.requestPermissions(MainActivity.this, new
                            String[] {Manifest.permission.CALL_PHONE}, 1)

3.申请权限后,系统会弹出一个权限申请框,不管如何操作,最终会回调

onRequestPermissionsResult(int requestCode, String[] permissions,
                                           int[] grantResult)

4.授权结果会封装在grantResult中,做最后判断是否授权成功。

int[0] grantResult == PackageManager.PERMISSION_GRANTED 

3 访问其他程序中的数据

Content Provider的用法由两种:

  • 1.使用现有的Content Provider来读取和操作相应程序中的数据;
  • 2.创建自己的Content Provider给我们程序的数据提供外部访问接口。

3.1 ContentResolver的基本用法

通过Context 中的getCOntentResolver()方法获得ContentResolver类的实例。
提供了方法用于对数据进行CRUD操作。(增加(Create)、读取(Read)、更新(Update)和删除(Delete))

  • insert()方法用于添加数据
  • update()方法用于更新数据
  • delete()方法用于删除数据
  • query()方法用于查询数据
    这些方法使用Uri参数,即内容URI,给Content Provider中的数据建立唯一标识符,两部分组成:authority和path。
    content头部协议声明
    authority是用于对不同的应用程序做区分,一般使用程序包名来命名。
    path则是用于对统一应用中不同的表做区分,通常会添加在authority后面。
    标准写法例子
content://com.example.app.provider/table1

内容URI字符串解析成Uri对象后,作为参数传入。

Uri uri = Uri.parse("content://com.example.app.provider/table1")

查询table1表数据,代码

Cursor cursor = getContentResolver().query(
	uri,//指定查询某个应用程序下的某一张表
	projection,//指定查询的列名
	selection,//指定where的约束条件
	selectionArgs,//为where的占位符提供具体符
	sortOrder);//指定查询结果的排序方式
	

将数据从Cursor对象中逐个读取处理。通过移动游标来遍历Cursor所有行,在取出每一行相应列的数据。

if (cursor != null && cursor.moveToFirst()) {
	do {
		Stirng colum1 = cursor.getString(cursor.getColumnIndex("column1"));//根据 name的名称获得它的列索引
		int colum2 = cursor.getInt(cursor.getColumnIndex("column2"));
	}while(cursor.moveToNext());
	cursor.close();
}

添加数据,先将待添加的数据组装子啊ContentValues 中,再调用ContentResolver的insert()方法。

ContentValues values = new ContentValues();
values.put("column1", "text");
values.put("column2", 1);
getContentResolver().insert(uri, values);

更新这条新添加的数据,把column1的值清空

ContentValues values = new ContentValues();
values.put("column1", "");
getContentResolver().update(uri, values, "column1 = ? and column2 = ?",
							new String[] {"text", "1"});

删除数据

getContentResolver().delete(uri, "column2 = ?", new Stirng[] { "1" }

3.2 读取系统联系人

判断权限

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
            != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new
                    String[] {Manifest.permission.READ_CONTACTS}, 2);
        } else {
            readContacts();
        }

回调返回值

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                           int[] grantResults) {
            case 2:
                if (grantResults.length > 0 && grantResults[0] ==
                PackageManager.PERMISSION_GRANTED) {
                    readContacts();
                } else {
                    Toast.makeText(this, "You denied the permssion",
                            Toast.LENGTH_SHORT).show();
                }
                break;
            default:
        }
    }

读取联系人

 private void readContacts() {
        Cursor cursor = null;
        try {
            cursor = getContentResolver().query(ContactsContract.CommonDataKinds.
                    Phone.CONTENT_URI, null, null, null, null);
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    String displayName = cursor.getString(cursor.getColumnIndex
                            (ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                    String number = cursor.getString(cursor.getColumnIndex
                            (ContactsContract.CommonDataKinds.Phone.NUMBER));
                    contactsList.add(displayName + "\n" + number);
                }
                adapter.notifyDataSetChanged();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }

AndroidManifest.xml声明权限

<uses-permission android:name="android.permission.READ_CONTACTS"/>

4 创建自己的内容提供器

4.1 创建内容提供器步骤

1.onCreate()
初始化ContentProvider时调用,完成对数据库的创建和升级。
只有当存在ContentResolver尝试访问我们程序中的数据时,ContentProvider才会被初始化。

2.query()
从ContentProvider中查询数据。查询结果存放在Cursor对象中返回。

  • Uri参数:确定查询哪一张表;
  • projection参数:确定查询哪些列;
  • selection和selectionArgs参数:用于约束查询哪些行;
  • sortOrder参数:用于对结果进行排序。

3.insert()
向ContentProvider添加一条数据。使用uri参数确定要添加到的表,待添加的数据保持在values参数中。添加完成后,返回一个用于表示这条新纪录的URI。

4.update()
更新ContentProvider已有的数据。使用uri参数确定要更新到的表,新数据保持在values参数中,selection和selectionArgs参数用于约束更新哪些行,受影响的行数将作为返回值返回。

5.delete()
从ContentProvider中删除数据。使用uri参数确定要删除的表,selection和selectionArgs参数用于约束删除哪些行,被删除的行数将作为返回值返回。

6.getType()
根据传入的内容URI来返回相应的MIME类型。

标准的内容URI写法扩展:
原本:
content://com.example.app.provider/table1
内容URI后面添加id
content://com.example.app.provider/table1/1
表示访问/com.example.app这个应用的table1表中id为1的数据
通配符:

  • *:表示匹配任意长度的任意字符;
  • #:表示匹配任意长度的数字。

使用UriMatcher类匹配内容URI
该类提供addURI()方法,接受三个参数,分别把authority、path和一个自定义代码传进去。
该类提供match()方法,传入一个Uri对象,返回值是某个能够匹配这个URI对象的自定义代码。通过这个代码,可以判断期望访问哪一个表。
使用该类可以判断使用哪一个表,然后再进行CRUD操作。

getType()方法,用于获取Uri对象所对应的MIME类型。一个内容URI所对应的MIME字符串主要三部分组成。

  • 必须以vnd开头
  • 如果内容URI以路径结尾,则vnd后面接android.cursor.dir/,如果以id结尾,则vnd后面接android.cursor.item/。
  • 最后接上vnd.. tip:不使用”/",用"."代替。
    例子:
    内容URI:content://com.example.app.provider/table1
    MIME:vnd.android.cursor.dir/vnd.com.example.app.provider.table1
    内容URI:content://com.example.app.provider/table1/1
    MIME:vnd.android.cursor.item/vnd.com.example.app.provider.table
    tip:id没了

4.2 实现跨程序数据共享

<provider
	android:name=".DatabaseProvider"
	android:name="com.example.databasetest.provider"
	android:enabled="true"
	android:exported="true">
</provider>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值