6.0动态权限这个问题,面试官很喜欢问这个。还有5.0、7.0新特性。
22以前的api,都是在AndroidManifest文件中注册权限即可,用户在安装apk的时候会有权限提示,但是哪个用户会看呢?google为了提高用户的安全性,在23(6.0)以后,app使用某一个敏感操作时,还需要用户的允许才行,否则这个功能无法使用。
动态权限就这么回事。
代码很简单,都有注释。
如果你不确定那些是敏感的权限,可以使用下面命令cmd进行查看:
在使用到敏感权限时,需要判断当前的版本是不是23以上。
如果不是,那就好办了,直接调用相关功能的方法即可。
如果需要呢?还得判断某权限是否已经授权。授权了也就不用再申请了。否则需要申请。
传递对应权限的参数,申请权限。然后在回调方法里面接受授权结果。根据结果再做处理即可。
看Activity用法。
22以前的api,都是在AndroidManifest文件中注册权限即可,用户在安装apk的时候会有权限提示,但是哪个用户会看呢?google为了提高用户的安全性,在23(6.0)以后,app使用某一个敏感操作时,还需要用户的允许才行,否则这个功能无法使用。
动态权限就这么回事。
先贴一下我的工具类吧:
/**
* @Author: duke
* @DateTime: 2017-03-30 15:51
* @Description: 权限检测工具类
*/
public class PermissionManager {
private PermissionManager() {
}
/**
* 是否需要动态申请权限 <br/>
*
* @return 需要:true,不需要:false
*/
public static final boolean isNeedDynamicPermissions() {
//if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {}
if (Build.VERSION.SDK_INT >= 23) {
// 23 (Android 6.0)以上
return true;
}
return false;
}
/**
* 向用户弹出解释对话框 <br/>
* *******************************************************************************
* ** 应用安装后第一次访问,直接返回false; **
* ** 第一次请求权限时用户拒绝了,下一次返回 true, **
* ** 这时候可以显示一些为什么需要这个权限的说明; **
* ** 第二次请求权限时,用户拒绝了,并选择了“不再提醒”的选项时,返回 false; **
* ** 设备的系统设置中禁止当前应用获取这个权限的授权,返回false; **
* ** 注意:第二次请求权限时,才会有“不再提醒”的选项, **
* ** 如果用户一直拒绝,并没有选择“不再提醒”的选项, **
* ** 下次请求权限时,会继续有“不再提醒”的选项,并且会一直返回true **
* *******************************************************************************
*
* @param activity 上下文
* @param permission 需要提示解释的权限申请
* @return 需要提示:true,不需要:false
*/
public static final boolean shouldShowRequestPermissionRationale(Activity activity, String permission) {
return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
}
/**
* 检查当前是否已被赋予权限 <br/>
*
* @param context 上下文
* @param permissions 待判断权限集合
* @return 授权:true,缺少授权:false
*/
public static final boolean checkSelfPermission(Context context, String... permissions) {
if (null == permissions || permissions.length == 0) {
return false;
}
for (String permission : permissions) {
if (TextUtils.isEmpty(permission)) {
return false;
}
/**
* 检测权限核心方法
*/
if (ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_DENIED) {
//如果其中某一个未授权
return false;
}
}
//权限参数合法,且全部都授权过
return true;
}
/**
* 正式请求用户授权 <br/>
*
* @param context activity上下文
* @param permissions 待权限的权限集合
* @param requestCode 本次授权请求码
*/
public static final void requestPermissions(Activity context, String[] permissions, int requestCode) {
ActivityCompat.requestPermissions(context, permissions, requestCode);
}
/**
* 检查授权结果,是否为“成功授权” <br/>
*
* @param grantResults 权限结果集合
* @return 授权成功:true,授权失败:false
*/
public static final boolean checkPermissionsResult(int[] grantResults) {
if (grantResults == null || grantResults.length == 0) {
return false;
}
for (int grantResult : grantResults) {
if (grantResult == PackageManager.PERMISSION_DENIED) {
//其中一个未授权,立即返回false授权失败
return false;
}
}
return true;
}
}
代码很简单,都有注释。
如果你不确定那些是敏感的权限,可以使用下面命令cmd进行查看:
//adb shell pm list permissions -d -g
在使用到敏感权限时,需要判断当前的版本是不是23以上。
如果不是,那就好办了,直接调用相关功能的方法即可。
如果需要呢?还得判断某权限是否已经授权。授权了也就不用再申请了。否则需要申请。
传递对应权限的参数,申请权限。然后在回调方法里面接受授权结果。根据结果再做处理即可。
看Activity用法。
/**
* 拨打电话
*/
public class CallActivity extends Activity {
private String phone;
public static final int PERMISSION_REQUEST_CODE_CALL_PHONE = 1900;
public static final String[] NEED_PERMISSIONS = {Manifest.permission.CALL_PHONE};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call);
phone = getIntent().getStringExtra("phone");
//检查6.0动态权限-拨打电话权限
check6Permission();
}
private void check6Permission() {
//判断权限
if (PermissionManager.isNeedDynamicPermissions()) {
//需要动态申请权限,判断是否授权
if (!PermissionManager.checkSelfPermission(getApplicationContext(), NEED_PERMISSIONS)) {
//申请授权
PermissionManager.requestPermissions(CallActivity.this, NEED_PERMISSIONS, PERMISSION_REQUEST_CODE_CALL_PHONE);
} else {
//已授权
callPhone();
}
} else {
//不需要动态权限
callPhone();
}
}
public void callPhone(){
if(TextUtils.isEmpty(phone)){
return;
}
Uri uri = Uri.parse("tel:" + phone);
Intent intent = new Intent();
intent.setData(uri);
intent.setAction(Intent.ACTION_CALL);
startActivity(intent);
finish();
}
/**
* 权限申请回调
*
* @param requestCode 请求码
* @param permissions 申请的权限字符串集合
* @param grantResults 申请的权限结果集合
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
//PERMISSION_REQUEST_CODE_CALL_PHONE 权限请求
if (requestCode == PERMISSION_REQUEST_CODE_CALL_PHONE) {
if (PermissionManager.checkPermissionsResult(grantResults)) {
//授权成功
callPhone();
} else {
//授权失败
if (null == permissions || permissions.length == 0) {
return;
}
//当此拒绝后,这儿立马为true
boolean isNeedShowExplainToUser = PermissionManager.shouldShowRequestPermissionRationale(this, permissions[0]);
if (isNeedShowExplainToUser) {
//需要向用户解释
DialogUtils.alertDialogTwo(this, 0, false, "没有此权限,将无法拨打电话",
"提示", "取消", "去设置",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//取消授权
CallActivity.this.finish();
}
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//应用程序详情页面
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
CallActivity.this.finish();
}
}).show();
}
finish();
}
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
都很简单,唯一需要特别说明的是:shouldShowRequestPermissionRationale(this, permissions[0]);方法。
个人觉得这个方法需要放在回调里面,即当用户拒绝后立即显示提示框。放在其他的地方无意义。
还有点需要特别说明的是,这个方法在某些厂商的系统中永远都为false,把人给坑死了,比喻小米系统。在测试这个功能的时候还是建议使用原版系统或者模拟器实验。
6.0动态权限就这点东西,不多说了。