Android在API 23之后开启了危险权限动态申请的机制,具体有哪些权限这里不做赘述,只拿笔者在手机和TV端开发中用到的权限例举,示例Demo并没有依赖任何的第三方库,纯Android代码,大约130行左右。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
ArrayList<String> needGetList = null;
for (String permission : mPermissions) {
// 检查是否已经授权
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_DENIED) {
if (needGetList == null){
needGetList = new ArrayList<>();
}
//没有授权,添加到待申请列表
needGetList.add(permission);
}
}
// 进行申请动作
actionPermission(needGetList, needGetList == null ? true : false);
}
private void actionPermission(ArrayList<String> needGetList, boolean result){
// 有需要申请的权限
if (needGetList != null && needGetList.size() > 0){
System.out.println(needGetList.toString());
String[] arrays = new String[needGetList.size()];
for (int i = 0; i < needGetList.size(); i++) {
arrays[i] = needGetList.get(i);
}
ActivityCompat.requestPermissions(this, arrays, MY_PERMISSIONS_REQUEST_READ_CONTACTS);
}else {
if (result){
// 授权成功
Toast.makeText(this, "授权成功", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(this, "授权失败,您可之后到系统应用管理页面进行手动授权", Toast.LENGTH_SHORT).show();
}
startActivity(new Intent(this, HomeActivity.class));
finish();
}
}
返回的permissions是所有发起申请的权限,grantResults是对应的申请结果,下标是一一对应的。判断grantResults的结果是不是PackageManager.PERMISSION_DENIED(被拒绝),如果有被拒绝的权限弹出对话框提示,如果没有则关闭页面。
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
ArrayList<String> denied = new ArrayList<>();
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_DENIED){
denied.add(permissions[i]);
}
}
if (denied.size() > 0 ){
// 有未申请到得权限 需要弹框提醒
showRationaleDialog(denied);
}else {
// 申请到所有权限 跳转页面
actionPermission(null, true);
}
}
}
}
点击继续授权跳转到系统应用管理中本应用的详情页面进行开启,点击取消提示用户授权失败并关闭页面(如遇必须权限可以提示用户不授权无法使用)
注:手机端打开详情页面没有问题,但部分TV盒子将应用详情给砍掉了,会打开失败。
/**
* 弹出提示语
*
*/
private void showRationaleDialog(final ArrayList<String> denied) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("提示");
TextView mMsg = new TextView(this);
mMsg.setText("您还有权限未授权完毕,将导致应用无法正常使用,是否跳转到系统设置界面继续授权?");
mMsg.setGravity(Gravity.CENTER_HORIZONTAL);
mMsg.setTextSize(18);
builder.setView(mMsg);
builder.setCancelable(false);
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
try{
// 打开系统 本应用的详情页面
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.fromParts("package", BeforeActivity.this.getPackageName(), null));
BeforeActivity.this.startActivity(intent);
}catch (Exception e){
Log.e(TAG, "打开当前本应用设置界面失败: " + e.getMessage());
try{
// 打开系统已安装应用页面
BeforeActivity.this.startActivity(new Intent(Settings.ACTION_APPLICATION_SETTINGS));
}catch (Exception e2){
Log.e(TAG, "打开应用设置界面失败: " + e.getMessage());
Toast.makeText(BeforeActivity.this, "打开应用设置界面失败", Toast.LENGTH_SHORT).show();
// 如果都打开失败 提示用户手动之后手动开启权限 并关闭页面
actionPermission(null, false);
}
}
toAppDetail = true;
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
actionPermission(null, false);
}
});
Dialog tipDialog = builder.create();
tipDialog.setCanceledOnTouchOutside(false);
tipDialog.show();
}
这里用的是重写onStart方法根据标志位来做的判断,页面重新可见后再次检查权限是否已经都可用,权限都可用就关闭页面,如果依然有未开启的权限则提示用户。
@Override
protected void onStart() {
super.onStart();
if (toAppDetail){
toAppDetail = false;
for (String permission : mPermissions) {
// 检查是否已经授权
if (ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_DENIED) {
actionPermission(null, false);
return;
}
}
actionPermission(null, true);
}
}
整体流程就是这样,经过测试目前在华为、荣耀、小米、vivo手机上都可以实现权限的动态申请,另外TV端在小米、天猫、当贝部分盒子上也可以实现动态获取。
Demo详情地址:https://github.com/TheTangEmperor/permissiondemo.git