Android 动态权限申请
ContextCompat.checkSelfPermission
检查应用是否具有某个危险权限。如果应用具有此权限,方法将返回PackageManager.PERMISSION_GRANTED,并且应用可以继续操作。如果应用不具有此权限,方法将返回PackageManager.PERMISSION_DENIED,且应用必须明确向用户要求权限。
ActivityCompat.requestPermissions
应用可以通过这个方法动态申请权限,调用后会弹出一个对话框提示用户授权所申请的权限
ActivityCompat.shouldShowRequestPermissionRationale
如果应用之前请求过此权限但是用户拒绝了此权限,此方法返回true。如果用户在过去拒绝了权限请求,并且在权限请求系统对话框中选择了不再提示这样的选项,此方法将返回false。如果设备规范禁止应用具有此权限,此方法也会返回false。
onRequestPermissionsResult
当应用请求权限时,系统将向用户显示一个对话框。当用户响应时,系统将调用应用的onRequestPermissionsResult()方法,向其传递用户响应,处理对应的场景。
下面以Android 12系统为例,分析系统对动态权限的处理流程
App申请动态权限代码
xml
Java
private static final int REQUEST_CAMERA_PERMISSION = 100; if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION); } else { // 权限已经被授予,可以使用相机功能 Log.w(TAG, "xww onCreate: is aleady ok"); } public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CAMERA_PERMISSION) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限被授予,可以使用相机功能 for (int i = 0; irequestPermissions
申请权限时启动权限控制应用,弹出窗口
@frameworks/base/core/java/android/app/Activity.java requestPermissions @frameworks/base/core/java/android/content/pm/PackageManager.java final Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions); Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS); //public static final String ACTION_REQUEST_PERMISSIONS = "android.content.pm.action.REQUEST_PERMISSIONS"; intent.putExtra(EXTRA_REQUEST_PERMISSIONS_NAMES, permissions); intent.setPackage(getPermissionControllerPackageName()); startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null); //packages/modules/Permission/PermissionController/AndroidManifest.xmlGrantPermissionsActivity
权限控制应用
@packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java onCreate @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt mViewHandler = new com.android.permissioncontroller.permission.ui.handheld.GrantPermissionsViewHandlerImpl(this, mCallingPackage, Process.myUserHandle()).setResultListener(this); @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt mViewModel = factory.create(GrantPermissionsViewModel.class); return GrantPermissionsViewModel(app, packageName, requestedPermissions.toList(), sessionId, init { GlobalScope.launch(Main.immediate) { mViewModel.getRequestInfosLiveData().observe(this, this::onRequestInfoLoad); onRequestInfoLoad @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt mRootView = mViewHandler.createView(); button!!.setOnClickListener(this) //弹出弹窗 GlobalScope.launch(Main.immediate) { val groups = packagePermissionsLiveData.getInitializedValue() for (gg in groups) { Log.w("xww", "xww init, gg=${gg}"); //gg=android.permission-group.CAMERA=[android.permission.CAMERA] //gg=android.permission-group.LOCATION=[android.permission.ACCESS_FINE_LOCATION, android.permission.ACCESS_COARSE_LOCATION, android.permission.ACCESS_BACKGROUND_LOCATION] for (requestedPerm in requestedPermissions) { Log.w("xww", "xww init, requestedPerm=$requestedPerm"); //requestedPerm=android.permission.CAMERA allAffectedPermissions.addAll(computeAffectedPermissions(requestedPerm, groups)) val extendedBySplitPerms = mutableListOf(perm) return extendedBySplitPerms unfilteredAffectedPermissions = allAffectedPermissions.toList() for (unfilteredAffectedPerm in unfilteredAffectedPermissions) { Log.w("xww", "xww init, unfilteredAffectedPerm=${unfilteredAffectedPerm}"); //unfilteredAffectedPerm=android.permission.CAMERA getAppPermGroups(groups.toMutableMap().apply { val requestedGroups = groups.filter { (_, perms) -> perms.any { it in unfilteredAffectedPermissions } //过滤出requestedGroups for (requestedGroup in requestedGroups) { Log.w("xww", "xww getAppPermGroups, requestedGroup=${requestedGroup}"); //getAppPermGroups, requestedGroup=android.permission-group.CAMERA=[android.permission.CAMERA] setSourcesToDifference(requestedGroups.keys, appPermGroupLiveDatas, getLiveDataFun) //viewModel,数据更新时调用onUpdate @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt onUpdate getRequestInfosFromGroupStates() requestInfos.add(RequestInfo(groupInfo, buttonVisibilities, locationVisibilities, message, detailMessage)) value = if (requestInfos.any { it.sendToSettingsImmediately } @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java onRequestInfoLoad mRequestInfos = requests; for(int i=0; i点击allow按键
@packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt onClick ALLOW_BUTTON -> if (resultListener != null) { @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java resultListener!!.onPermissionGrantResult(groupName, affectedForegroundPermissions,GRANTED_ALWAYS) //2. 获取groupName, 1处设置 Log.w(LOG_TAG, "xww onPermissionGrantResult 2, name=" + name + " result=" + result + " affectedForegroundPermissions=" + affectedForegroundPermissions); //onPermissionGrantResult 2, name=android.permission-group.CAMERA result=1 affectedForegroundPermissions=null logGrantPermissionActivityButtons(name, affectedForegroundPermissions, result); @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt mViewModel.onPermissionGrantResult(name, affectedForegroundPermissions, result); GRANTED_ALWAYS -> { onPermissionGrantResultSingleState(foregroundGroupState, affectedForegroundPermissions, granted = true, isOneTime = false, doNotAskAgain = false) @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt KotlinUtils.grantForegroundRuntimePermissions(app, groupState.group, groupState.affectedPermissions, isOneTime) return grantRuntimePermissions(app, group, true, false, filterPermissions) for (permName in filterPermissions) { val (newPerm, shouldKill) = grantRuntimePermission(app, perm, isOneTime, group) @frameworks/base/core/java/android/permission/PermissionManager.java app.packageManager.grantRuntimePermission(group.packageName, perm.name, user) @frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java mPermissionManager.grantRuntimePermission(packageName, permissionName, user.getIdentifier()); grantRuntimePermissionInternal(packageName, permName, overridePolicy, callingUid, userId, mDefaultPermissionCallback); callback.onPermissionGranted(uid, userId); //通过PermissionCallback将权限申请结果回调给PKMS,PermissionCallback是在PKMS实现的 mOnPermissionChangeListeners.onPermissionsChanged(uid); mPackageManagerInt.writeSettings(true); reportRequestResult(groupState.affectedPermissions, result) //打印log for (perm in permissions) { reportRequestResult(perm, result) Log.v(LOG_TAG, "Permission grant result requestId=$sessionId " + "callingUid=${packageInfo.uid} callingPackage=$packageName permission=$permission " + "isImplicit=$isImplicit result=$result") //Permission grant result requestId=-7157070073027897334 callingUid=10058 callingPackage=com.example.androidimu permission=android.permission.WRITE_EXTERNAL_STORAGE isImplicit=false result=4 //Permission grant result requestId=-7157070073027897334 callingUid=10058 callingPackage=com.example.androidimu permission=android.permission.READ_EXTERNAL_STORAGE isImplicit=true result=4 requestInfosLiveData.update() onUpdate getRequestInfosFromGroupStates() value = if (requestInfos.any { it.sendToSettingsImmediately } @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java onRequestInfoLoad else if (requests.isEmpty()) { mRequestInfos = requests; setResultAndFinish(); return; showNextRequest(); //显示下一个权限请求 if (mRequestInfos == null || mRequestInfos.isEmpty()) { return;@packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java onCreate @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt mViewHandler = new com.android.permissioncontroller.permission.ui.handheld.GrantPermissionsViewHandlerImpl(this, mCallingPackage, Process.myUserHandle()).setResultListener(this); @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt mViewModel = factory.create(GrantPermissionsViewModel.class); return GrantPermissionsViewModel(app, packageName, requestedPermissions.toList(), sessionId, init { GlobalScope.launch(Main.immediate) { mViewModel.getRequestInfosLiveData().observe(this, this::onRequestInfoLoad); onRequestInfoLoad @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/handheld/GrantPermissionsViewHandlerImpl.kt mRootView = mViewHandler.createView(); button!!.setOnClickListener(this) //弹出弹窗 GlobalScope.launch(Main.immediate) { val groups = packagePermissionsLiveData.getInitializedValue() for (gg in groups) { Log.w("xww", "xww init, gg=${gg}"); //gg=android.permission-group.CAMERA=[android.permission.CAMERA] //gg=android.permission-group.LOCATION=[android.permission.ACCESS_FINE_LOCATION, android.permission.ACCESS_COARSE_LOCATION, android.permission.ACCESS_BACKGROUND_LOCATION] for (requestedPerm in requestedPermissions) { Log.w("xww", "xww init, requestedPerm=$requestedPerm"); //requestedPerm=android.permission.CAMERA allAffectedPermissions.addAll(computeAffectedPermissions(requestedPerm, groups)) val extendedBySplitPerms = mutableListOf(perm) return extendedBySplitPerms unfilteredAffectedPermissions = allAffectedPermissions.toList() for (unfilteredAffectedPerm in unfilteredAffectedPermissions) { Log.w("xww", "xww init, unfilteredAffectedPerm=${unfilteredAffectedPerm}"); //unfilteredAffectedPerm=android.permission.CAMERA getAppPermGroups(groups.toMutableMap().apply { val requestedGroups = groups.filter { (_, perms) -> perms.any { it in unfilteredAffectedPermissions } //过滤出requestedGroups for (requestedGroup in requestedGroups) { Log.w("xww", "xww getAppPermGroups, requestedGroup=${requestedGroup}"); //getAppPermGroups, requestedGroup=android.permission-group.CAMERA=[android.permission.CAMERA] setSourcesToDifference(requestedGroups.keys, appPermGroupLiveDatas, getLiveDataFun) //viewModel,数据更新时调用onUpdate @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt onUpdate getRequestInfosFromGroupStates() requestInfos.add(RequestInfo(groupInfo, buttonVisibilities, locationVisibilities, message, detailMessage)) value = if (requestInfos.any { it.sendToSettingsImmediately } @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java onRequestInfoLoad mRequestInfos = requests; for(int i=0; i if (resultListener != null) { @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java resultListener!!.onPermissionGrantResult(groupName, affectedForegroundPermissions,GRANTED_ALWAYS) //2. 获取groupName, 1处设置 Log.w(LOG_TAG, "xww onPermissionGrantResult 2, name=" + name + " result=" + result + " affectedForegroundPermissions=" + affectedForegroundPermissions); //onPermissionGrantResult 2, name=android.permission-group.CAMERA result=1 affectedForegroundPermissions=null logGrantPermissionActivityButtons(name, affectedForegroundPermissions, result); @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/model/GrantPermissionsViewModel.kt mViewModel.onPermissionGrantResult(name, affectedForegroundPermissions, result); GRANTED_ALWAYS -> { onPermissionGrantResultSingleState(foregroundGroupState, affectedForegroundPermissions, granted = true, isOneTime = false, doNotAskAgain = false) @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/utils/KotlinUtils.kt KotlinUtils.grantForegroundRuntimePermissions(app, groupState.group, groupState.affectedPermissions, isOneTime) return grantRuntimePermissions(app, group, true, false, filterPermissions) for (permName in filterPermissions) { val (newPerm, shouldKill) = grantRuntimePermission(app, perm, isOneTime, group) @frameworks/base/core/java/android/permission/PermissionManager.java app.packageManager.grantRuntimePermission(group.packageName, perm.name, user) @frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java mPermissionManager.grantRuntimePermission(packageName, permissionName, user.getIdentifier()); grantRuntimePermissionInternal(packageName, permName, overridePolicy, callingUid, userId, mDefaultPermissionCallback); callback.onPermissionGranted(uid, userId); //通过PermissionCallback将权限申请结果回调给PKMS,PermissionCallback是在PKMS实现的 mOnPermissionChangeListeners.onPermissionsChanged(uid); mPackageManagerInt.writeSettings(true); reportRequestResult(groupState.affectedPermissions, result) //打印log for (perm in permissions) { reportRequestResult(perm, result) Log.v(LOG_TAG, "Permission grant result requestId=$sessionId " + "callingUid=${packageInfo.uid} callingPackage=$packageName permission=$permission " + "isImplicit=$isImplicit result=$result") //Permission grant result requestId=-7157070073027897334 callingUid=10058 callingPackage=com.example.androidimu permission=android.permission.WRITE_EXTERNAL_STORAGE isImplicit=false result=4 //Permission grant result requestId=-7157070073027897334 callingUid=10058 callingPackage=com.example.androidimu permission=android.permission.READ_EXTERNAL_STORAGE isImplicit=true result=4 requestInfosLiveData.update() onUpdate getRequestInfosFromGroupStates() value = if (requestInfos.any { it.sendToSettingsImmediately } @packages/modules/Permission/PermissionController/src/com/android/permissioncontroller/permission/ui/GrantPermissionsActivity.java onRequestInfoLoad else if (requests.isEmpty()) { mRequestInfos = requests; setResultAndFinish(); return; showNextRequest(); //显示下一个权限请求 if (mRequestInfos == null || mRequestInfos.isEmpty()) { return;
(图片来源网络,侵删)(图片来源网络,侵删)(图片来源网络,侵删)