简而言之,在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);
}