Android startActivityForResult对应的onActivityResult和onRequestPermissionsResult是怎么来的

简而言之,在Activity finish时会将resultCode和resultIntent的数据打包放在原来的Activity的ActivityRecord里面,在这个Activity重新resume时,会将ActivityResult的数据提取出来进行处理,是动态权限的就调onRequestPermissionsResult,一般情况下就回调onActivityResult。

Activity setResult,设置resultCode和Intent

    public final void setResult(int resultCode, Intent data) {
        synchronized (this) {
            mResultCode = resultCode;
            mResultData = data;
        }
    }

比如PackageInstaller的GrantPermissionsActivity

    private void setResultIfNeeded(int resultCode) {
        if (!mResultSet) {
            mResultSet = true;
            logRequestedPermissionGroups();
            Intent result = new Intent(PackageManager.ACTION_REQUEST_PERMISSIONS);
            result.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES, mRequestedPermissions);
            result.putExtra(PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS, mGrantResults);
            setResult(resultCode, result);
        }
    }

还有再往前的启动它

    public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
        if (requestCode < 0) {
            throw new IllegalArgumentException("requestCode should be >= 0");
        }
        if (mHasCurrentPermissionsRequest) {
            Log.w(TAG, "Can request 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;

 

然后是finish,带上result data

    private void finish(int finishTask) {
        if (mParent == null) {
            int resultCode;
            Intent resultData;
            synchronized (this) {
                resultCode = mResultCode;
                resultData = mResultData;
            }
            if (false) Log.v(TAG, "Finishing self: token=" + mToken);
            try {
                if (resultData != null) {
                    resultData.prepareToLeaveProcess(this);
                }
                if (ActivityManager.getService()
                        .finishActivity(mToken, resultCode, resultData, finishTask)) {
                    mFinished = true;
                }
            } catch (RemoteException e) {
                // Empty
            }

ams交给ActivityStack去处理

                    res = tr.getStack().requestFinishActivityLocked(token, resultCode,
                            resultData, "app-request", true);
                    if (!res) {
                        Slog.i(TAG, "Failed to finish by app-request");
                    }

ActivityStack::finishActivityLocked

            r.pauseKeyDispatchingLocked();

            adjustFocusedActivityStack(r, "finishActivity");

            finishActivityResultsLocked(r, resultCode, resultData);

            final boolean endTask = index <= 0 && !task.isClearingToReuseTask();

ActivityStack::finishActivityResultsLocked 

ActivityRecord resultTo就是要将结果传给它的那个启动的Activity的ActivityRecord

            resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
                                     resultData);

在relaunch启动并resume Activity时会带上result data,并将其封装在ActivityRelaunchItem中,最终由ClientTransactionHandler的实现类ActivityThread在performResumeActivity进行处理,这里的事务处理过程不研究,主要是封装了binder通信的过程。

    void relaunchActivityLocked(boolean andResume, boolean preserveWindow) {
        if (service.mSuppressResizeConfigChanges && preserveWindow) {
            configChangeFlags = 0;
            return;
        }

        List pendingResults = null;
        List pendingNewIntents = null;
        if (andResume) {
            pendingResults = results;
            pendingNewIntents = newIntents;
        }
        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
                "Relaunching: " + this + " with results=" + pendingResults
                        + " newIntents=" + pendingNewIntents + " andResume=" + andResume
                        + " preserveWindow=" + preserveWindow);
        EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY
                        : AM_RELAUNCH_ACTIVITY, userId, System.identityHashCode(this),
                task.taskId, shortComponentName);

        startFreezingScreenLocked(app, 0);

        try {
            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
                    "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
                            + " callers=" + Debug.getCallers(6));
            forceNewConfig = false;
            mStackSupervisor.activityRelaunchingLocked(this);
            final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
                    pendingNewIntents, configChangeFlags,
                    new MergedConfiguration(service.getGlobalConfiguration(),
                            getMergedOverrideConfiguration()),
                    preserveWindow);
            final ActivityLifecycleItem lifecycleItem;
            if (andResume) {
                lifecycleItem = ResumeActivityItem.obtain(service.isNextTransitionForward());
            } else {
                lifecycleItem = PauseActivityItem.obtain();
            }
            final ClientTransaction transaction = ClientTransaction.obtain(app.thread, appToken);
            transaction.addCallback(callbackItem);
            transaction.setLifecycleStateRequest(lifecycleItem);
            service.getLifecycleManager().scheduleTransaction(transaction);
            // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
            // request resume if this activity is currently resumed, which implies we aren't
            // sleeping.
        } catch (RemoteException e) {
            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
        }

        if (andResume) {
            if (DEBUG_STATES) {
                Slog.d(TAG_STATES, "Resumed after relaunch " + this);
            }
            results = null;
            newIntents = null;
            service.getAppWarningsLocked().onResumeActivity(this);
            service.showAskCompatModeDialogLocked(this);

ActivityThread::performResumeActivity

如果还有pendingResults就去开始执行,逻辑到这里基本上就结束了。

            if (r.pendingResults != null) {
                deliverResults(r, r.pendingResults, reason);
                r.pendingResults = null;
            }

 和最开始的requestPermissions对应,会最终调用onRequestPermissionResult进行处理。如果是一般的情况,就直接调用onActivityResult。到这里就搞清楚了为什么在GrantPermissionsActivity setResult就可以最终将grant的结果在onRequestPermissionResult体现出来。

    private void deliverResults(ActivityClientRecord r, List results, String reason) {
        final int N = results.size();
        for (int i=0; i
    void dispatchActivityResult(String who, int requestCode, int resultCode, Intent data,
            String reason) {
        if (false) Log.v(
            TAG, "Dispatching result: who=" + who + ", reqCode=" + requestCode
            + ", resCode=" + resultCode + ", data=" + data);
        mFragments.noteStateNotSaved();
        if (who == null) {
            onActivityResult(requestCode, resultCode, data);
        } else if (who.startsWith(REQUEST_PERMISSIONS_WHO_PREFIX)) {
            who = who.substring(REQUEST_PERMISSIONS_WHO_PREFIX.length());
            if (TextUtils.isEmpty(who)) {
                dispatchRequestPermissionsResult(requestCode, data);
            } else {
                Fragment frag = mFragments.findFragmentByWho(who);
                if (frag != null) {
                    dispatchRequestPermissionsResultToFragment(requestCode, data, frag);
                }
            }
        } else if (who.startsWith("@android:view:")) {
            ArrayList views = WindowManagerGlobal.getInstance().getRootViews(
                    getActivityToken());
            for (ViewRootImpl viewRoot : views) {
                if (viewRoot.getView() != null
                        && viewRoot.getView().dispatchActivityResult(
                                who, requestCode, resultCode, data)) {
                    return;
                }
            }
        } else if (who.startsWith(AUTO_FILL_AUTH_WHO_PREFIX)) {
            Intent resultData = (resultCode == Activity.RESULT_OK) ? data : null;
            getAutofillManager().onAuthenticationResult(requestCode, resultData, getCurrentFocus());
        } else {
            Fragment frag = mFragments.findFragmentByWho(who);
            if (frag != null) {
                frag.onActivityResult(requestCode, resultCode, data);
            }
        }
        writeEventLog(LOG_AM_ON_ACTIVITY_RESULT_CALLED, reason);
    }
    private void dispatchRequestPermissionsResult(int requestCode, Intent data) {
        mHasCurrentPermissionsRequest = false;
        // If the package installer crashed we may have not data - best effort.
        String[] permissions = (data != null) ? data.getStringArrayExtra(
                PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES) : new String[0];
        final int[] grantResults = (data != null) ? data.getIntArrayExtra(
                PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS) : new int[0];
        onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

 

你可能感兴趣的:(Android startActivityForResult对应的onActivityResult和onRequestPermissionsResult是怎么来的)