Android权限 - 动态权限申请系统流程

话不多说直接上流程图:

1.checkSelfPermission

2.requestPermissions

 

因为都不是很复杂的流程,所以也咩有太多需要说明的,除了以下两点需要稍微知道下,算是自己记录下:

1.在checkSelfPermission流程中
调用到ActivityManager(frameworks\base\core\java\android\app\ActivityManager.java)中的方法checkComponentPermission比较重要
在这个方法中,可以知道root及systemuid的进程的权限直接PERMISSION_GRANTED。

public static int checkComponentPermission(String permission, int uid,
        int owningUid, boolean exported) {
    // Root, system server get to do everything.
    final int appId = UserHandle.getAppId(uid);
    if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
        return PackageManager.PERMISSION_GRANTED;
    }
    // Isolated processes don't get any permissions.
    if (UserHandle.isIsolated(uid)) {
        return PackageManager.PERMISSION_DENIED;
    }
    // If there is a uid that owns whatever is being accessed, it has
    // blanket access to it regardless of the permissions it requires.
    if (owningUid >= 0 && UserHandle.isSameApp(uid, owningUid)) {
        return PackageManager.PERMISSION_GRANTED;
    }
    // If the target is not exported, then nobody else can get to it.
    if (!exported) {
        /*
        RuntimeException here = new RuntimeException("here");
        here.fillInStackTrace();
        Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid,
                here);
        */
        return PackageManager.PERMISSION_DENIED;
    }
    if (permission == null) {
        return PackageManager.PERMISSION_GRANTED;
    }
    try {
        return AppGlobals.getPackageManager()
                .checkUidPermission(permission, uid);
    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

2.在requestPermissions流程中
会调用到AppPermissionGroup(packages\apps\PermissionController\src\com\android\packageinstaller\permission\model\AppPermissionGroup.java)中的方法persistChanges
在这个方法中,可以知道在权限进行revoke时会先进行判断当前权限是否为PERMISSION_GRANTED,只有是才会进行revoke。

void persistChanges(boolean mayKillBecauseOfAppOpsChange) {
    int uid = mPackageInfo.applicationInfo.uid;

    int numPermissions = mPermissions.size();
    boolean shouldKillApp = false;

    for (int i = 0; i < numPermissions; i++) {
        Permission permission = mPermissions.valueAt(i);

        if (!permission.isSystemFixed()) {
            if (permission.isGranted()) {
                mPackageManager.grantRuntimePermission(mPackageInfo.packageName,
                        permission.getName(), mUserHandle);
            } else {
                boolean isCurrentlyGranted = mContext.checkPermission(permission.getName(), -1,
                        uid) == PERMISSION_GRANTED;

                if (isCurrentlyGranted) {
                    mPackageManager.revokeRuntimePermission(mPackageInfo.packageName,
                            permission.getName(), mUserHandle);
                }
            }
        }

        int flags = (permission.isUserSet() ? PackageManager.FLAG_PERMISSION_USER_SET : 0)
                | (permission.isUserFixed() ? PackageManager.FLAG_PERMISSION_USER_FIXED : 0)
                | (permission.shouldRevokeOnUpgrade()
                ? PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE : 0)
                | (permission.isPolicyFixed() ? PackageManager.FLAG_PERMISSION_POLICY_FIXED : 0)
                | (permission.isReviewRequired()
                ? PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED : 0);

        mPackageManager.updatePermissionFlags(permission.getName(),
                mPackageInfo.packageName,
                PackageManager.FLAG_PERMISSION_USER_SET
                        | PackageManager.FLAG_PERMISSION_USER_FIXED
                        | PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE
                        | PackageManager.FLAG_PERMISSION_POLICY_FIXED
                        | PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED,
                flags, mUserHandle);

        if (permission.affectsAppOp()) {
            if (!permission.isSystemFixed()) {
                // Enabling/Disabling an app op may put the app in a situation in which it has
                // a handle to state it shouldn't have, so we have to kill the app. This matches
                // the revoke runtime permission behavior.
                if (permission.isAppOpAllowed()) {
                    shouldKillApp |= allowAppOp(permission, uid);
                } else {
                    shouldKillApp |= disallowAppOp(permission, uid);
                }
            }
        }
    }

    if (mayKillBecauseOfAppOpsChange && shouldKillApp) {
        killApp(KILL_REASON_APP_OP_CHANGE);
    }

    if (mTriggerLocationAccessCheckOnPersist) {
        new LocationAccessCheck(mContext, null).checkLocationAccessSoon();
        mTriggerLocationAccessCheckOnPersist = false;
    }
}

 

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 应用中,有一些需要用户授权才能访问的敏感权限,比如读取联系人、摄像头、定位等权限。在 Android 6.0(API Level 23)及以上版本中,系统引入了动态权限申请机制,应用需要在运行时动态申请这些权限。 以下是 Android 动态申请权限的基本流程: 1. 在 AndroidManifest.xml 文件中声明需要申请权限,例如: ``` <uses-permission android:name="android.permission.CAMERA" /> ``` 2. 在应用中检查是否拥有该权限,如果没有则向用户申请权限。 ``` if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, MY_PERMISSIONS_REQUEST_CAMERA); } ``` 3. 实现回调方法 onRequestPermissionsResult(),处理用户的权限选择结果。 ``` @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == MY_PERMISSIONS_REQUEST_CAMERA) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限已授予,执行相应操作 } else { // 权限被拒绝,提示用户并做相应处理 } return; } } ``` 以上就是 Android 动态申请权限的基本流程。需要注意的是,在申请权限前需要先检查是否已经授权,如果已经授权则可以直接执行相应操作,否则需要向用户申请权限。此外,在处理用户的权限选择结果时,需要根据 requestCode 参数进行判断,以确定是哪个权限申请结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值