存在的意义:

在Android 6.0之后(SDK >22)对于Runtime Permission严格控制,在第三方应用打开Runtime permission

的时候系统需要提醒用户,一般的情况下,Runtime permission 默认的权限是denied 的,应用需要获取应用就必要申请,在request 的时候会弹出一个跟用户交互的提示框,而这些就是GrantPermissionActivity 存在的意义。

下面来看下GrantPermissionsActivity 注册的信息:

                                                                        
先来看此Activity 注册的地方,在action 为android.content.pm.action.REQUEST_PERMISSIONS的时候触发。 再来看Activity.java 中的 requestPermissions:
 public final void requestPermissions(@NonNull String[] permissions, int requestCode) {        if (requestCode < 0) { //requestCode 必须为正数            throw new IllegalArgumentException("requestCode should be >= 0");        }        if (mHasCurrentPermissionsRequest) {            Log.w(TAG, "Can reqeust only one set of permissions at a time");            // Dispatch the callback with empty arrays which means a cancellation.            onRequestPermissionsResult(requestCode, new String[0], new int[0]);            return;        }        Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);        startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null);        mHasCurrentPermissionsRequest = true;    }
其中buildRequestPermissionsIntent 用来创建所需的intent:
    public Intent buildRequestPermissionsIntent(@NonNull String[] permissions) {        if (ArrayUtils.isEmpty(permissions)) {           throw new IllegalArgumentException("permission cannot be null or empty");        }        Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS);        intent.putExtra(EXTRA_REQUEST_PERMISSIONS_NAMES, permissions);        intent.setPackage(getPermissionControllerPackageName());        return intent;    }
首先传的action 就是GrantPermissionsActivity 所需要的action,这个intent 还将需要request 的permissions 带入,最关键的是指定了intent 所指向的package 为PackageInstaller。
到此,我们知道GrantPermissionsActivity 存在是为了处理requestPermissions。

分析源码:

详细的源码可以看:packages/apps/PackageInstaller/src/com/android/packageinstaller/permission/ui/GrantPermissionsActivity.java 主要偏向于UI 逻辑的控制,在这里主要总计几个重要部分:
1、mRequestedPermissions
这个是通过intent 的extra 传过来的,extra 的name 是PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES
        mRequestedPermissions = getIntent().getStringArrayExtra(                PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES);
2、GrantPermissionsViewHandlerImpl
这个是用来更新activity UI的重要类
    mViewHandler = new com.android.packageinstaller.permission.ui.handheld            .GrantPermissionsViewHandlerImpl(this, getCallingPackage())            .setResultListener(this);
3、setContentView(mViewHandler.createView());
acitivity 将GrantPermissionsViewHandlerImpl 中的createView 出来的View 显示出来。
4、mAppPermissions
            mAppPermissions = new AppPermissions(this, callingPackageInfo, null, false,                new Runnable() {                    @Override                    public void run() {                        setResultAndFinish();                    }                });
这个AppPermissions 其实就是单个应用所拥有的所有的group permission 的统计,详细看 private final ArrayList mGroups = new ArrayList<>();
5、showNextPermissionGroupGrantRequest
读取request 的group 相关信息,通过mViewHandler.updateUi 来更新UI。
mViewHandler.updateUi(groupState.mGroup.getName(), groupCount, currentIndex,Icon.createWithResource(resources, icon), message,groupState.mGroup.isUserSet());
6、onClick
    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,                            AppPermissionGroup.isStrictOpEnable() ? 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;        }    }
提示框的click 事件是在GrantPermissionsViewHandlerImpl 这里处理的,最后会通过callback 调回到GrantPermissionsActivity 中。
7、onPermissionGrantResult
    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 {                if (!AppPermissionGroup.isStrictOpEnable()) {                    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();        }    }
这里的callback 是从GrantPermissionsViewHandlerImpl 回来,确定执行grant 还是revoke。


总结:

其实核心思想就是想通过request 的时候跟用户进行交互,弹出一个提示框。CTA也是这样要求的,存在一个疑问就是,如果第三方应用直接调用check permission 之后grant permission,而不通过request 怎么办,那这样可能就没有交互了。详细可以 看下android grantRuntimePermission 详解




更多相关文章

  1. Android简明开发教程六:用户界面设计
  2. 2011.06.07(2)——— android 调试android源码包下的package应用的
  3. 【30篇突击 android】源码统计 十八
  4. Android消息处理机制——AsyncTask 源码解析
  5. 【实习周记】Android getevent.c源码分析
  6. 超级清爽android计算器界面源码

随机推荐

  1. Android Architecture Components 之 Vie
  2. 将Canvas保存为一个bitmap
  3. 关于CTS中android.permission.cts.Debugg
  4. Android系统SystemServer进程启动过程源
  5. Android高亮引导控件的实现代码
  6. 我的android 第28天 - Activity(一)
  7. Android Permission中英文对照表
  8. Android POST data and COOKIES
  9. NDK与JNI
  10. Android 颜色对照表