一、Android权限介绍:
Android在访问受限的沙盒中运行应用,访问沙盒外的资源是受到限制的(包括读写用户的私有数据(如联系人)、读写其他应用的文件、执行网络访问、使设备保持唤醒状态)。在6.0之前,应用在安装时,所请求的权限都被授予,这样的话就会造成一些不必要的权限的授予,否则无法安装使用。在6.0之后,引入了运行时权限机制,即对于那些危险(涉及用户隐私)的权限,需要在运行过程中进行授予。
进程级安全限制,让任何两个应用都不能在同一进程中运行,因为它们需要作为不同的 Linux 用户运行(Android 为每个软件包提供唯一的 Linux 用户 ID)。但可以在每个软件包的 AndroidManifest.xml 的 manifest 标记中使用 sharedUserId 属性,为它们分配相同的用户 ID。这样做以后,出于安全目的,两个软件包将被视为同一个应用,具有相同的用户 ID 和文件权限。注意,为保持安全性,只有两个签署了相同签名(并且请求相同的 sharedUserId)的应用才被分配同一用户 ID。
二、在Manifest中声明权限:
对于沙盒未提供的功能,需要申明访问权限,使用<uses-permission android:name="..."/>。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.snazzyapp">
<uses-permission android:name="android.permission.SEND_SMS"/>
<application ...>
...
</application>
</manifest>
在Manifest中申明的权限,如果是普通权限,则在安装时,就自动授予了,如果是危险权限,则需要运行时确认。
三、运行时请求权限:
在Android6.0之前,所有权限都列在清单文件中,必须在安装时授权,不授权则无法安装。
在6.0(API23)之后,Android引入了运行时权限的概念,将系统权限分为两种:
正常权限:不会对用户隐私造成风险的权限。在manifet中声明则系统自动授予。
危险权限:涉及到用户隐私数据的权限。需要用户在运行时授予这些权限。
1.检查权限:
// 检测权限是否授予
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// 检测该全是是否被拒绝,同时提供一个解释,为何需要此权限
// 如果用户在过去拒绝了权限请求,并在权限请求系统对话框中选择了 Don't ask again 选项,
// 此方法将返回 false。如果设备规范禁止应用具有该权限,此方法也会返回 false
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// 显示一个解释用的提示,之后尝试再次请求该权限。
} else {
// 如果不显示解释,则请求权限
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS 是自定义的请求码
}
}
2.处理权限请求响应:
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// 如果请求取消了,数组将是空的
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 权限请求通过,可以执行权限相关的操作
} else {
// 未授权,不允许执行权限相关操作
}
return;
}
// 其他的权限请求
}
}
注意:
1)授权提示框不显示具体权限,而是整个权限组。如READ_CONTACTS,显示要访问设备联系人。用户只要为权限组授权一次,以后该权限组其他权限请求将默认授予。但是 其它权限仍要请求,因为权限分组在将来的 Android 版本中可能会发生变化。不应依赖特定权限属于或不属于相同组这种假设。
2)如果用户拒绝了某项权限请求,应该有个提示。例如,可以显示一个对话框,解释为什么需要该权限。
3)当系统要求用户授予权限时,用户可以选择指示系统不再要求提供该权限。requestPermissions() 再次要求该权限,系统会立即拒绝,直接调用onRequestPermissionsResult() 方法,并传递 PERMISSION_DENIED。
四、权限建议:
a.可以用Intent取代权限。例如,当你想做个拍照的功能时,可以用intent请求别的应用来完成,之后返回照片。这样既不用申请权限,也省得自己写个照相机(界面,功能等等);
b.申请自己所需的权限,甚至可以用a中的方法精简权限数量;
b.申请自己所需的权限,甚至可以用a中的方法精简权限数量;
c.在哪里需要则在哪里进行权限申请,不要全部在启动时就开始申请权限;
d.在必要时解释一下为何应用要申请该权限;
e.适配6.0+。在6.0之前我们可以很放心的使用我们在Manifest中申请的权限,但是在6.0之后,我们必须要在运行时进行权限的检查。因此,测试时要两种情况都测。