内容提供器简介
内容提供器(Content Provider)主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。使用内容提供器是Android实现跨程序共享数据的标准方式。
内容提供器可以选择只对哪一部分数据进行共享,从而保证我们程序中的隐私数据不会有泄漏的风险。
运行时权限
Android权限机制详解
在Android 6.0系统后加入了运行时权限功能。用户不需要在安装软件的时候一次性授权所有申请的权限,而是可以在软件的使用过程中再对某一项权限进行授权。
Android将所有的权限归位两类,一类是普通权限,一类是危险权限。
普通权限指的是那些不会直接威胁用户的安全和隐私的权限,对于这部分权限申请,系统会自动帮我们进行授权,而不需要用户再去手动操作。
危险权限指的是那些可能会触及用户隐私或者对设备安全性造成影响的权限,如获取设备联系人信息、定位设备的地理位置等,对于这部分权限申请,必须要由用户手动点击授权才可以,否则程序就无法使用相应的功能。
访问https://developer.android.google.cn/reference/android/Manifest.permission.html可以查看Android系统中完整的权限列表。
在程序运行时申请权限
修改androidManifest文件,在其中声明如下权限:
<uses-permission android:name="android.permission.CALL_PHONE" />
把拨打电话的逻辑封装到call()方法当中:
private void call() {
try {
Intent intent = new Intent(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10010"));
startActivity(intent);
} catch (SecurityException e) {
e.printStackTrace();
}
}
构建了一个隐私Intent,Intent的action指定为Intent.ACTION_CALL,这是一个系统内置的打电话的动作,然后在data部分指定了协议是tel,号码是10086.
Button makeCall = (Button) findViewById(R.id.make_call);
makeCall.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//判断用户是否已授权
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CALL_PHONE)
!= PackageManager.PERMISSION_GRANTED) {
//若没有授权
//调用ActivityCompat.requestPermissions()方法来向用户申请授权
ActivityCompat.requestPermissions(MainActivity.this,
new String[] { Manifest.permission.CALL_PHONE}, 1);
} else {
//若已授权
//调用封装的call()方法
call();
}
}
});
第一步先判断用户是否已经给过我们授权了,借助的是ContextCompat.checkSelfPermission()方法,然后使用方法返回值和PackageManager.PERMISSION_GRANTED做比较,相等就说明用户已经授权,反之则未授权。
如果已经授权则直接去执行拨打电话的逻辑操作即可,此处把逻辑封装到了call()方法当中。如果没有授权,则需要调用ActivityCompat.requestPermissions()方法来向用户申请授权。
ContextCompat.checkSelfPermission()方法
作用:
判断用户是否已授权
参数:
1. Context
2. 具体的权限名,如打电话就是Manifest.permission.CALL_PHONE
返回:
返回值和PackageManager.PERMISSION_GRANTED做比较,若相等则已授权,反之未授权
ActivityCompat.requestPermissions()方法
作用:
向用户申请授权
参数:
1. Activity的实例
2. String数组,把要申请的权限名放在数组中即可
3. 请求码,唯一值即可
回调:
回调onRequestPermissionsResult()方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
call();
} else {
Toast.makeText(this, "You denied the permission", Toast.LENGTH_LONG).show();
}
break;
default:
}
}
调用完了requestPermission()方法之后,系统会弹出一个权限申请的对话框,用户选择后会回调到onRequestPermissionsResult()方法中,授权的结果会封装到grantResults参数当中。
访问其他程序中的数据
内容提供器的用法一般有两种。
一种是使用现有的内容提供器来读取和操作相应程序中的数据。
一种是创建自己的内容提供器给我们程序的数据提供外部访问接口。
ContentResolver的基本用法
对于每一个应用程序来说,如果想要访问内容提供器中共享的数据,必须借助ContentResolver类。
通过Context中的getContentResolver()方法获取该类的实例。
ContentResolver中提供了一系列的方法用于对数据进行CRUD操作,其中insert()方法用于添加数据,update()方法用于更新数据,delete()方法用于删除数据,query()方法用于查询数据。
ContentResolver中的增删改查方法都是不接受表名参数的,而是使用一个Uri参数代替,这个参数被称为内容URI。
内容URI给内容提供器中的数据建立了唯一标识符,主要有两部分组成:authority和path。authority用于对不同的应用程序作区分,一般为了避免冲突,都会采用程序包名的方式来进行命名。path则用于对同一应用程序中不同的表做区分,通常都会添加到authority的后面。
内容URI标准的格式写法如下:
content://com.example.app.provider/table1
content://com.example.app.provider/table2
内容URI可以清晰的表达出想要访问哪个应用程序中哪张表的数据。
得到内容URI字符串后,需要将其解析成Uri对象才可以作为参数传入:
Uri uri = Uri.parse("content://com.cunxie.app.provider/table1");
只需要调用Uri.parse()方法即可。
查query()
Cursor cursor = getContentResolver().query(
uri,
projection,
selection,
selectionArgs,
sortOrder);
query()方法参数 |