android 8.0权限弹框点击确定,应用会退出
程序员文章站
2022-06-06 09:20:32
...
在项目开发中遇到申请权限的弹框,点击允许,这个应用会退出,百度也没找到原因,只能根据代码定位问题了
首先,显示权限弹框的逻辑在packages/apps/PackageInstaller中,点击事件在GrantPermissionsViewHandlerImpl.java中,
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.permission_allow_button:
if (mResultListener != null) {
view.performAccessibilityAction(
AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
mResultListener.onPermissionGrantResult(mGroupName, true, false);
}
break;
case R.id.permission_deny_button:
mAllowButton.setEnabled(true);
if (mResultListener != null) {
view.performAccessibilityAction(
AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
mResultListener.onPermissionGrantResult(mGroupName, false,
mShowDonNotAsk && mDoNotAskCheckbox.isChecked());
}
break;
case R.id.permission_more_info_button:
Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSIONS);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mAppPackageName);
intent.putExtra(ManagePermissionsActivity.EXTRA_ALL_PERMISSIONS, true);
mActivity.startActivity(intent);
break;
case R.id.do_not_ask_checkbox:
mAllowButton.setEnabled(!mDoNotAskCheckbox.isChecked());
break;
}
}
允许控件的ID是R.id.permission_allow_button,允许权限的具体实现是
mResultListener.onPermissionGrantResult(mGroupName, true, false);
mResultListener是在GrantPermissionsActivity.java实现的
@Override
public void onPermissionGrantResult(String name, boolean granted, boolean doNotAskAgain) {
GroupState groupState = mRequestGrantPermissionGroups.get(name);
if (groupState.mGroup != null) {
if (granted) {
groupState.mGroup.grantRuntimePermissions(doNotAskAgain,
groupState.affectedPermissions);
groupState.mState = GroupState.STATE_ALLOWED;
} else {
groupState.mGroup.revokeRuntimePermissions(doNotAskAgain,
groupState.affectedPermissions);
groupState.mState = GroupState.STATE_DENIED;
int numRequestedPermissions = mRequestedPermissions.length;
for (int i = 0; i < numRequestedPermissions; i++) {
String permission = mRequestedPermissions[i];
if (groupState.mGroup.hasPermission(permission)) {
EventLogger.logPermissionDenied(this, permission,
mAppPermissions.getPackageInfo().packageName);
}
}
}
updateGrantResults(groupState.mGroup);
}
if (!showNextPermissionGroupGrantRequest()) {
setResultAndFinish();
}
}
继续执行
groupState.mGroup.grantRuntimePermissions(doNotAskAgain,
groupState.affectedPermissions);
走到AppPermissionGroup.java中
public boolean grantRuntimePermissions(boolean fixedByTheUser, String[] filterPermissions) {
final int uid = mPackageInfo.applicationInfo.uid;
for (Permission permission : mPermissions.values()) {
if (filterPermissions != null
&& !ArrayUtils.contains(filterPermissions, permission.getName())) {
continue;
}
if (!permission.isGrantingAllowed(mIsEphemeralApp, mAppSupportsRuntimePermissions)) {
// Skip unallowed permissions.
continue;
}
if (mAppSupportsRuntimePermissions) {
// Do not touch permissions fixed by the system.
if (permission.isSystemFixed()) {
return false;
}
// Ensure the permission app op enabled before the permission grant.
if (permission.hasAppOp() && !permission.isAppOpAllowed()) {
permission.setAppOpAllowed(true);
mAppOps.setUidMode(permission.getAppOp(), uid, AppOpsManager.MODE_ALLOWED);
}
// Grant the permission if needed.
if (!permission.isGranted()) {
permission.setGranted(true);
mPackageManager.grantRuntimePermission(mPackageInfo.packageName,
permission.getName(), mUserHandle);
}
// Update the permission flags.
if (!fixedByTheUser) {
// Now the apps can ask for the permission as the user
// no longer has it fixed in a denied state.
if (permission.isUserFixed() || permission.isUserSet()) {
permission.setUserFixed(false);
permission.setUserSet(false);
mPackageManager.updatePermissionFlags(permission.getName(),
mPackageInfo.packageName,
PackageManager.FLAG_PERMISSION_USER_FIXED
| PackageManager.FLAG_PERMISSION_USER_SET,
0, mUserHandle);
}
}
} else {
.
.
.
}
}
return true;
}
申请权限执行到
mPackageManager.grantRuntimePermission(mPackageInfo.packageName,permission.getName(),mUserHandle);
在framework/base/services/core/java/com/android/server/pm/PackageManagerService.java
@Override
public void grantRuntimePermission(String packageName, String name, final int userId) {
grantRuntimePermission(packageName, name, userId, false /* Only if not fixed by policy */);
}
private void grantRuntimePermission(String packageName, String name, final int userId,
boolean overridePolicy) {
...
...
synchronized (mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
if (pkg == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
...
...
final int result = permissionsState.grantRuntimePermission(bp, userId);
switch (result) {
case PermissionsState.PERMISSION_OPERATION_FAILURE: {
return;
}
case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
final int appId = UserHandle.getAppId(pkg.applicationInfo.uid);
mHandler.post(new Runnable() {
@Override
public void run() {
killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED);
}
});
}
break;
}
...
...
}
}
看到 killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED)这个方法,就知道应用退出的原因了,将这个方法注释掉就可以了