现状:
1、当代码编译版本都是 5.0及其以下(API23以下),在Manifest注册了权限。
运行在6.0以下手机没有问题,用户只能在安装的时候选择同意权限,不能修改(不考虑第三方安全软件设置的因素)
运行在6.0及其以上,对于敏感权限用户可以在设置中修改(不需要第三方软件),修改时系统会提示用户“可能会导致无法正常运行”,但还可以修改成功。一旦修改了在API23以下是没有办法在程序内部通过API的方法打开权限。对于非敏感权限安装后无法修改。
2、当代码编译版本都是 6.0及其以上(API23及其以上),在Manifest注册了权限。
运行在6.0以下手机没有问题,用户只能在安装的时候选择同意权限,不能修改(不考虑第三方安全软件设置的因素)
运行在6.0及其以上
,
对于
非
敏感权限安装后即可获取该权限,也无法修改。
对于敏感权限安装后默认是没有权限的。程序内部可以判断、提示用户赋予这些权限。
Android6.0与权限相关的API
//检查是否已赋予某个权限,返回
PackageManager.
PERMISSION_GRANTED或
PERMISSION_DENIED
ContextCompat.checkSelfPermission()
//向用户请求赋予某个(某些)权限
ActivityCompat.requestPermissions()
//向用户请求赋予权限的结果
OnRequestPermissionsResultCallback()
//Google提供的一个人性化的方法,表示是否向用户解释一下权限
ActivityCompat.shouldShowRequestPermissionRationale()
FragmentCompat.requestPermissions()
OnRequestPermissionsResultCallback()
FragmentCompat.shouldShowRequestPermissionRationale()
示例:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
readExtStorageDir();
}
/**
* 读取外部SD卡目录
*/
private void readExtStorageDir() {
int permissionResult = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
if (PackageManager.PERMISSION_GRANTED == permissionResult) {//已有权限
doReadExtStorageDir();
} else {//没有权限向用户索取权限
final String[] permissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE};
ActivityCompat.requestPermissions(MainActivity.this, permissions, 100);
}
}
/**
* 索取权限的结果
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (100 == requestCode) {
if (null != permissions) {
//是读取外部SD卡的权限&已赋予权限
if (Manifest.permission.READ_EXTERNAL_STORAGE.equals(permissions[0]) && PackageManager.PERMISSION_GRANTED == grantResults[0]) {
doReadExtStorageDir();
}
}
}
}
private void doReadExtStorageDir() {
File storageDir = Environment.getExternalStorageDirectory();
File[] files = storageDir.listFiles();
if (null != files && files.length > 0) {
for (File f : files) {
Log.e("P", "==>" + f.getName());
}
}
}
}
个性化提示:
当用户拒绝后,但又没有点不再提示,那么这个时候是否给用户一个对权限要求的说明呢?这个时候就用到shouldShowRequestPermissionRationale方法
shouldShowRequestPermissionRationale()的理解:
如果之前请求过并被用户拒绝,那么它会返回 true,如果之前用户已经勾选了不再提示的选项,它会返回 false,同样当设备策略禁止应用拥有这条权限时也会返回 false。第一次请求这个权限也返回false。那么我们需要做的,就是在用户确切需要拒绝这个权限请求前向他解释我们为什么需要,否则当彻底拒绝后(用户在拒绝的时候勾选了不再提示也返回false,但执行requestPermissions()方法不会显示请求权限框),除非用户手动去设置中开启,我们都无法再得到权限了。
/** * 读取外部SD卡目录 */ private void readExtStorageDir() { int permissionResult = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE); if (PackageManager.PERMISSION_GRANTED == permissionResult) { doReadExtStorageDir(); } else { final String[] permissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}; boolean shouldShowRequestPermission = ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE); Log.e("P", "shouldShowRequestPermission==" + shouldShowRequestPermission); if (shouldShowRequestPermission) { showMessageOKCancel("向用户解释权限,请用户点击允许!", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { ActivityCompat.requestPermissions(MainActivity.this, permissions, 100); } }); return; } ActivityCompat.requestPermissions(MainActivity.this, permissions, 100); } }
一次请求多个权限:
//定义请求多个权限的名称 String[] permissions = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}; //向用户请求赋予权限 ActivityCompat.requestPermissions(MainActivity.this,permissions,100);
//回调结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); Log.e("P", requestCode + " " + permissions[0] + " " + grantResults[0]); if (100 == requestCode) { if (null != permissions) { for (int i = 0; i < permissions.length; i++) { Log.e("P", permissions[i] + " ===> " + grantResults[i]); if (Manifest.permission.READ_EXTERNAL_STORAGE.equals(permissions[i])) { if (PackageManager.PERMISSION_GRANTED == grantResults[i]) { doReadExtStorageDir(); } } } } } }
权限组
ActivityCompat.requestPermissions()不能传权限组名称,只能传权限名称,同一组的任何一个权限被授权了,其他权限也自动被授权。
敏感权限列表
权限组 | 权限 |
---|---|
android.permission-group.CALENDAR(日历数据) |
|
android.permission-group.CAMERA(相机) |
|
android.permission-group.CONTACTS(联系人) |
|
android.permission-group.LOCATION(位置) |
|
android.permission-group.MICROPHONE(麦克风) |
|
android.permission-group.PHONE(电话) |
|
android.permission-group.SENSORS(传感器) |
|
android.permission-group.SMS(短信) |
|
android.permission-group.STORAGE(存储) |
|