Android权限申请

554 阅读3分钟

1 权限分类

  • 安装时权限

系统会在应用安装时自动授予应用相应权限,包括普通权限和签名权限。

  • 运行时权限

运行时权限也称为危险权限,Android 6.0 开始需要在应用中执行权限申请相关代码,系统会弹出授权框提示框,需要用户点击才可以授权。

  • 特殊权限

Android 6.0 开始需要用户在应用设置界面中才能开启权限。

基本上每个版本,权限都会有一定的修改,而且系统对这方面的限制是越来越严格,所以正确的做法是请求最少数量的权限。

2 特殊权限

这类权限需要在使用的时候用户动态申请。比如:当用户打开相机拍摄照片的时候,需要开发人员通过代码的方式在打开相机的地方去申请权限

注意: 权限是分组的,同一组的权限申请其中一个,同组的权限就全部都申请了。比如,应用被授予READ_EXTERNAL_STORAGE权限之后,如果再申请WRITE_EXTERNAL_STORAGE权限,系统会立即授予该权限,不会再弹出权限授予询问的对话框。

普通权限,只需要在AndroidManifest.xml中申请即可

特殊权限组

权限组权限
CALENDAR 日历permission:android.permission.READ_CALENDAR permission:android.permission.WRITE_CALENDAR
CAMERA 相机permission:android.permission.CAMERA
CONTACTS 联系人permission:android.permission.WRITE_CONTACTS permission:android.permission.GET_ACCOUNTS permission:android.permission.READ_CONTACTS
LOCATION 定位permission:android.permission.ACCESS_FINE_LOCATION permission:android.permission.ACCESS_COARSE_LOCATION
MICROPHONE麦克风相关,比如录音permission:android.permission.RECORD_AUDIO
PHONE 手机状态permission:android.permission.READ_CALL_LOG permission:android.permission.READ_PHONE_STATE permission:android.permission.CALL_PHONE permission:android.permission.WRITE_CALL_LOG permission:android.permission.USE_SIP permission:android.permission.PROCESS_OUTGOING_CALLS permission:com.android.voicemail.permission.ADD_VOICEMAI
SENSORS 传感器permission:android.permission.BODY_SENSORS
SMS 短信permission:android.permission.READ_SMS permission:android.permission.RECEIVE_WAP_PUSH permission:android.permission.RECEIVE_MMS permission:android.permission.RECEIVE_SMS permission:android.permission.SEND_SMS permission:android.permission.READ_CELL_BROADCASTS
STORAGE 存储权限permission:android.permission.READ_EXTERNAL_STORAGE permission:android.permission.WRITE_EXTERNAL_STORAGE

3 动态权限申请

checkSelfPermission(@NonNull Context context, @NonNull String permission)//检查是否开启权限。
requestPermissions(Activity activity, String[] permissions, int requestCode)//请求开启权限
  1. 动态权限申请也要在AndroidManifest.xml里面写明
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  1. 判断当前是否有权限
if (PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(context, permission)) {
    //已授权
} else {
    //未授权
}
  1. 进行权限申请
ActivityCompat.requestPermissions(context, permissions, mRequestCode);
  1. 用户授权后操作
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    PermissionsUtils.getInstance().onRequestPermissionsResult(this,requestCode,permissions,grantResults);
}

完整代码: 最好使用工具类,封装成单例

public class PermissionsUtils {
​
   private final int mRequestCode = 1001;//权限请求码
   public static boolean showSystemSetting = true;
   AlertDialog mPermissionDialog;
   private List<String> mPermissionList;
​
   private PermissionsUtils() {
   }
​
   private static PermissionsUtils permissionsUtils;
   private IPermissionsResult mPermissionsResult;
​
   public static PermissionsUtils getInstance() {
      if (permissionsUtils == null) {
         permissionsUtils = new PermissionsUtils();
      }
      return permissionsUtils;
   }
​
   public void checkPermissions(Activity context, String[] permissions, IPermissionsResult permissionsResult) {
      mPermissionsResult = permissionsResult;
​
      if (Build.VERSION.SDK_INT < 23) {//6.0才用动态权限
         permissionsResult.passPermissions();
      }
​
      //创建一个mPermissionList,逐个判断哪些权限未授予,未授予的权限存储到mPermissionList中
      mPermissionList = new ArrayList<>();
      //逐个判断你要的权限是否已经通过
      for (int i = 0; i < permissions.length; i++) {
         if (ContextCompat.checkSelfPermission(context, permissions[i]) != PackageManager.PERMISSION_GRANTED) {
            mPermissionList.add(permissions[i]);//添加还未授予的权限
         }
      }
​
      //申请权限
      if (mPermissionList.size() > 0) {//有权限没有通过,需要申请
         ActivityCompat.requestPermissions(context, permissions, mRequestCode);
      } else {
         //说明权限都已经通过
         permissionsResult.passPermissions();
      }
   }
​
​
   /**
    * 请求权限后回调的方法
    * @param context
    * @param requestCode  自定义的权限请求码
    * @param permissions  请求的权限数组
    * @param grantResults 在弹出页面后是否允许权限的标识数组,数组的长度对应的是权限名称数组的长度,数组的数据0表示允许权限,-1表示我们点击了禁止权限
    */
   public void onRequestPermissionsResult(Activity context, int requestCode, String[] permissions, int[] grantResults) {
      boolean hasPermissionDismiss = false;//有权限没有通过
      if (mRequestCode == requestCode) {
         for (int i = 0; i < grantResults.length; i++) {
            if (grantResults[i] == -1) {
               hasPermissionDismiss = true;
            }
         }
         //如果有权限没有被允许
         if (hasPermissionDismiss) {
            if (showSystemSetting) {
               showSystemPermissionsSettingDialog(context);//跳转到系统设置权限页面,或者直接关闭页面,不让他继续访问
            } else {
               mPermissionsResult.forbidPermissions();
            }
         } else {
            //全部权限通过,可以进行下一步操作
            mPermissionsResult.passPermissions();
         }
      }
​
   }
​
​
   /**
    * 不再提示权限时的展示对话框
    */
   private void showSystemPermissionsSettingDialog(final Activity context) {
      final String mPackName = context.getPackageName();
      if (mPermissionDialog == null) {
         mPermissionDialog = new AlertDialog.Builder(context)
               .setMessage("已禁用权限,请手动授予")
               .setPositiveButton("设置", new DialogInterface.OnClickListener() {
                  @Override
                  public void onClick(DialogInterface dialog, int which) {
                     cancelPermissionDialog();
​
                     Uri packageURI = Uri.parse("package:" + mPackName);
                     Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, packageURI);
                     context.startActivity(intent);
                     context.finish();
                  }
               })
               .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                  @Override
                  public void onClick(DialogInterface dialog, int which) {
                     //关闭页面或者做其他操作
                     cancelPermissionDialog();
                     //mContext.finish();
                     mPermissionsResult.forbidPermissions();
                  }
               }).create();
      }
      mPermissionDialog.show();
   }
​
   //关闭对话框
   private void cancelPermissionDialog() {
      if (mPermissionDialog != null) {
         mPermissionDialog.dismiss();
         mPermissionDialog = null;
      }
​
   }
​
   public interface IPermissionsResult {
      void passPermissions();
​
      void forbidPermissions();
   }
}

\