天天看点

【Android】6.0 运行时权限申请 整理

Android官方资料地址:

运行时权限申请

https://developer.android.com/training/permissions/requesting.html

权限列表

https://developer.android.com/guide/topics/security/permissions.html#defining

###1、校验权限的回调接口

自定义的回调接口,后面会用到
public interface CheckPermissionListener {

    /**
     * 授权成功
     * @param permissionName    具体取值参照 Manifest.permission.XXX_XX
     */
    void onPermissionGranted(String permissionName);

    /**
     * 授权失败
     * @param permissionName    具体取值参照 Manifest.permission.XXX_XX
     */
    void onPermissionDenied(String permissionName);

}
           

###2、从谷歌的官方文档可以看到,权限申请被多次拒绝之后(没有勾选不再询问),系统是可以给出权限申请的申请说明,即为什么要使用这个权限。

  • 2.1、ActivityCompat.shouldShowRequestPermissionRationale(this, permissionName)

    a.返回True。权限申请被多次拒绝之后(没有勾选不再询问)

    b.返回False。权限申请被多次拒绝之后(勾选不再询问);用户已经同意了权限申请。

  • 2.2、ContextCompat.checkSelfPermission(this,permissionName)

    权限检查。返回-1(PackageManager.PERMISSION_DENIED)和0(PackageManager.PERMISSION_GRANTED)

  • 2.3、权限申请对话框
ActivityCompat.requestPermissions(this, new String[] { permissionName },REQUEST_CODE_PERMISSIONS_REQUEST);
权限申请对话框,第二个参数标示申请的权限列表,第三个则是该申请的请求码(REQUEST_CODE,联想下就会知道会有结果回调)。
           
  • 2.4、申请权限的回调
/**
 * 申请权限的回调
 *
 * @param requestCode
 * @param permissions
 * @param grantResults
 */
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[],
									   int[] grantResults) {
}
           

###3、为了给调用提供及时的结果通知。我这边使用回调的方式,使调用者被动的接受结果。

  • 3.1、首先为了能够针对不同的权限给出权限申请说明。我这边定义了一个map。在需要给出提示的地方,根据当前权限名(key)获得说明。
/**
 * 权限申请说明,即为什么要申请此权限的权限说明集合
 * Key  权限名
 * Value    权限申请说明
 */
private static HashMap<String, String>                  permissionExplanationMap = new HashMap<>();

//初始化权限申请说明的集合
static {
	//暂无
}
           
  • 3.2、为了管理权限申请的回调,我这边又定义了回调的集合。在获得权限结果之后,出发回调方法、
/**
 * 权限申请回调处理集合
 * Key  权限名
 * Value    权限申请回调处理接口
 */
private static HashMap<String, CheckPermissionListener> permissionCallBackMap    = new HashMap<>();
           

###4、最终整理了两个方法

  • 4.1、权限校验
/**
 * 校验权限是否授予
 * @param permissionName          具体取值参照 Manifest.permission.XXX_XX
 * @param checkPermissionListener 授权结果的回调
 */
public void checkPermission(String permissionName,
							CheckPermissionListener checkPermissionListener) {
	if (TextUtils.isEmpty(permissionName)) {
		if (checkPermissionListener != null) {
			checkPermissionListener.onPermissionDenied(permissionName);
		}
		return;
	}

	//添加回调
	if (permissionCallBackMap.containsKey(permissionName)) {
		permissionCallBackMap.remove(permissionName);
	}
	permissionCallBackMap.put(permissionName, checkPermissionListener);
	if (ContextCompat.checkSelfPermission(this,
		permissionName) != PackageManager.PERMISSION_GRANTED) {
		if (checkPermissionListener != null) {
			checkPermissionListener.onPermissionDenied(permissionName);
		}
	} else {
		if (checkPermissionListener != null) {
			checkPermissionListener.onPermissionGranted(permissionName);
		}
	}
}
           
  • 4.2、权限校验和申请
/**
 * 校验(并申请)权限
 *
 * @param permissionName          具体取值参照 Manifest.permission.XXX_XX
 * @param checkPermissionListener 授权结果的回调
 */
public void checkAndRequestPermission(String permissionName,
									  CheckPermissionListener checkPermissionListener) {
	if (TextUtils.isEmpty(permissionName)) {
		LogUtil.d("权限名称为空,授权检查失败");
		if (checkPermissionListener != null) {
			checkPermissionListener.onPermissionDenied(permissionName);
		}
		return;
	}

	//添加回调
	if (permissionCallBackMap.containsKey(permissionName)) {
		permissionCallBackMap.remove(permissionName);
	}
	permissionCallBackMap.put(permissionName, checkPermissionListener);

	// Here, thisActivity is the current activity
	if (ContextCompat.checkSelfPermission(this,
		permissionName) != PackageManager.PERMISSION_GRANTED) {

		LogUtil.d("授权检查(" + permissionName + "),尚未授权");
		// 是否需要展示权限申请说明,即为什么要申请此权限
		if (ActivityCompat.shouldShowRequestPermissionRationale(this, permissionName)) {
			// Show an expanation to the user *asynchronously* -- don't block
			// this thread waiting for the user's response! After the user
			// sees the explanation, try again to request the permission.
			if (permissionExplanationMap.containsKey(permissionName)) {
				toast(permissionExplanationMap.get(permissionName) + "");
			}
			LogUtil.d("授权检查失败(" + permissionName + "),给出权限申请说明");
			if (checkPermissionListener != null) {
				checkPermissionListener.onPermissionDenied(permissionName);
			}
		} else {
			LogUtil.d("授权检查(" + permissionName + "),发起授权申请");
			// No explanation needed, we can request the permission.
			ActivityCompat.requestPermissions(this, new String[] { permissionName },
				REQUEST_CODE_PERMISSIONS_REQUEST);
			// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
			// app-defined int constant. The callback method gets the
			// result of the request.
		}
	} else {
		LogUtil.d("授权检查(" + permissionName + "),已授权。");
		if (checkPermissionListener != null) {
			checkPermissionListener.onPermissionGranted(permissionName);
		}
	}
}
           

###5、最终代码如下

/**
 * 权限申请回调处理集合
 * Key  权限名
 * Value    权限申请回调处理接口
 */
private static HashMap<String, CheckPermissionListener> permissionCallBackMap    = new HashMap<>();

/**
 * 权限申请说明,即为什么要申请此权限的权限说明集合
 * Key  权限名
 * Value    权限申请说明
 */
private static HashMap<String, String>                  permissionExplanationMap = new HashMap<>();

//初始化权限申请说明的集合
static {
	//暂无
}

//权限申请的请求代码
private static final int REQUEST_CODE_PERMISSIONS_REQUEST = 10;

/**
 * 校验权限是否授予
 * @param permissionName          具体取值参照 Manifest.permission.XXX_XX
 * @param checkPermissionListener 授权结果的回调
 */
public void checkPermission(String permissionName,
							CheckPermissionListener checkPermissionListener) {
	if (TextUtils.isEmpty(permissionName)) {
		if (checkPermissionListener != null) {
			checkPermissionListener.onPermissionDenied(permissionName);
		}
		return;
	}

	//添加回调
	if (permissionCallBackMap.containsKey(permissionName)) {
		permissionCallBackMap.remove(permissionName);
	}
	permissionCallBackMap.put(permissionName, checkPermissionListener);
	if (ContextCompat.checkSelfPermission(this,
		permissionName) != PackageManager.PERMISSION_GRANTED) {
		if (checkPermissionListener != null) {
			checkPermissionListener.onPermissionDenied(permissionName);
		}
	} else {
		if (checkPermissionListener != null) {
			checkPermissionListener.onPermissionGranted(permissionName);
		}
	}
}

/**
 * 校验(并申请)权限
 *
 * @param permissionName          具体取值参照 Manifest.permission.XXX_XX
 * @param checkPermissionListener 授权结果的回调
 */
public void checkAndRequestPermission(String permissionName,
									  CheckPermissionListener checkPermissionListener) {
	if (TextUtils.isEmpty(permissionName)) {
		LogUtil.d("权限名称为空,授权检查失败");
		if (checkPermissionListener != null) {
			checkPermissionListener.onPermissionDenied(permissionName);
		}
		return;
	}

	//添加回调
	if (permissionCallBackMap.containsKey(permissionName)) {
		permissionCallBackMap.remove(permissionName);
	}
	permissionCallBackMap.put(permissionName, checkPermissionListener);

	// Here, thisActivity is the current activity
	if (ContextCompat.checkSelfPermission(this,
		permissionName) != PackageManager.PERMISSION_GRANTED) {

		LogUtil.d("授权检查(" + permissionName + "),尚未授权");
		// 是否需要展示权限申请说明,即为什么要申请此权限
		if (ActivityCompat.shouldShowRequestPermissionRationale(this, permissionName)) {
			// Show an expanation to the user *asynchronously* -- don't block
			// this thread waiting for the user's response! After the user
			// sees the explanation, try again to request the permission.
			if (permissionExplanationMap.containsKey(permissionName)) {
				toast(permissionExplanationMap.get(permissionName) + "");
			}
			LogUtil.d("授权检查失败(" + permissionName + "),给出权限申请说明");
			if (checkPermissionListener != null) {
				checkPermissionListener.onPermissionDenied(permissionName);
			}
		} else {
			LogUtil.d("授权检查(" + permissionName + "),发起授权申请");
			// No explanation needed, we can request the permission.
			ActivityCompat.requestPermissions(this, new String[] { permissionName },
				REQUEST_CODE_PERMISSIONS_REQUEST);
			// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
			// app-defined int constant. The callback method gets the
			// result of the request.
		}
	} else {
		LogUtil.d("授权检查(" + permissionName + "),已授权。");
		if (checkPermissionListener != null) {
			checkPermissionListener.onPermissionGranted(permissionName);
		}
	}
}

/**
 * 申请权限的回调
 *
 * @param requestCode
 * @param permissions
 * @param grantResults
 */
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[],
									   int[] grantResults) {
	String permission = "";
	if (permissions != null) {
		permission = permissions[0];
	}
	//如果请求的权限为空,则不再继续处理
	if (TextUtils.isEmpty(permission)) {
		return;
	}

	LogUtil.d("授权(" + Arrays.toString(permissions) + ")申请结果(0=GRANTED;-1=DENIED):"
			  + Arrays.toString(grantResults));
	//获得权限的回调
	CheckPermissionListener checkPermissionListener = permissionCallBackMap.get(permission);
	switch (requestCode) {
		case REQUEST_CODE_PERMISSIONS_REQUEST: {
			// If request is cancelled, the result arrays are empty.
			if (grantResults.length > 0
				&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
				// permission was granted, yay! Do the
				// contacts-related task you need to do.
				if (checkPermissionListener != null) {
					//已授权
					checkPermissionListener.onPermissionGranted(permission);
				}
			} else {
				// permission denied, boo! Disable the
				// functionality that depends on this permission.
				if (checkPermissionListener != null) {
					//拒绝
					checkPermissionListener.onPermissionDenied(permission);
				}
			}
			return;
		}
		// other 'case' lines to check for other
		// permissions this app might request
	}
}