Activity的啟動過程
首先先列出Activity啟動的過程中調(diào)用的一些方法,因為activity啟動涉及到各種方法調(diào)用幔妨,而且調(diào)用的路線也各不一樣,這里只會對activity啟動的一條線進行分析谍椅,有興趣的同學(xué)可以讀android的源碼進行分析
- Activity
- startActivity
- startActivityForResult
- Instrumentation
- execStartActivity
- ActivityManagerProxy
- startActivity
- ActivityManagerService
- startActivity
- startActivityAsUser
- ActivityStarter
- startActivityMayWait
- startActivityLocked
- startActivityUnchecked
- postStartActivityUncheckedProcessing
- ActivityStack
- startActivityLocked
- ActivityStackSupervisor
- resumeFocusedStackTopActivityLocked
- ActivityStack
- resumeTopActivityUncheckedLocked
- resumeTopActivityInnerLocked
- ActivityThread
- scheduleLaunchActivity
- H(Handler) - LAUNCH_ACTIVITY
通過源碼發(fā)現(xiàn)误堡,startActivity進入到startActivityForResult的方法,然后進入到Instrumentation的execStartActivity方法雏吭。
在進入Instrumentation之前锁施,先對Instrumentation做簡短的介紹:
-
其包含有2個內(nèi)部類:ActivityMoniter、ActivityResult
ActivityMoniter:有關(guān)特定的Intent的監(jiān)視杖们。一個ActivityMoniter類的實例通過函數(shù)addMonitor(Instrumentation.ActivityMonitor)添加到當(dāng)前instrumentation中悉抵,一旦添加后,每當(dāng)啟動一個新的Activity摘完,ActivityMoniter就會檢測姥饰,如果匹配,其hit count計數(shù)更新等其他操作孝治。 一個ActivityMonitor也可以用來尋找一個Activity列粪,通過waitForActivity()方法,這個函數(shù)將返直到匹配的活動被創(chuàng)建谈飒。
ActivityResult:一個活動執(zhí)行的結(jié)果說明岂座,返回到原來的活動。 創(chuàng)建步绸,暫停和恢復(fù)Activity的時候掺逼,都是通過調(diào)用Instrumentation的callActivityOnCreate,callActivityOnPause和callActivityOnResume等方法來實現(xiàn)對Activity方法生命周期調(diào)用
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
// 跳出Activity方法瓤介,進入到execStartActivity方法
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
// 通知Activity啟動的結(jié)果吕喘,這里會調(diào)用棧頂?shù)腁ctivity調(diào)用onPause方法
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
// 這里是低版本的系統(tǒng)啟動Activity的方式,這里不進行分析
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
我們進入到Instrumentation的execStartActivity方法,下面對execStartActivity的參數(shù)進行解析,
從源碼可以看出刑桑,Instrumentation直接進入了ActivityManagerNative的startActivity方法氯质,隨后會調(diào)用checkStartActivityResult,這個方法會檢查返回結(jié)果是否中Activity是否在AndroidManifest.xml中注冊,如果沒有就會拋出異常等祠斧。
public class Instrumentation {
...省略代碼
public ActivityResult execStartActivity(...省略參數(shù)) {
...省略代碼
// 進入到ActivityManagerProxy
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
// 檢查startActivity返回結(jié)果是否成功
checkStartActivityResult(result, intents[0]);
...省略代碼
return null;
}
public static void checkStartActivityResult(...省略參數(shù)) {
if (res >= ActivityManager.START_SUCCESS) {
return;
}
switch (res) {
...省略代碼
// 此處是沒有在AndroidManifest.xml里注冊Activity時報的
case ActivityManager.START_INTENT_NOT_RESOLVED:
case ActivityManager.START_CLASS_NOT_FOUND:
if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
throw new ActivityNotFoundException(
"Unable to find explicit activity class "
+ ((Intent)intent).getComponent().toShortString()
+ "; have you declared this activity in your AndroidManifest.xml?");
throw new ActivityNotFoundException(
"No Activity found to handle " + intent);
...省略代碼
}
}
...省略代碼
}
然后我們進入到ActivityManagerNative,下面對Activity的參數(shù)進行分析
- who:Activity的啟動者
- contextThread:當(dāng)前Activity的啟動進程
- token:記錄啟動Activity的token值闻察,有可能為空
- target:啟動者,即啟動新Activity的那個Activity
- intent:意圖
- requestCode:啟動Activity后,返回給當(dāng)前Activity的值辕漂,通過onActivityResult返回
- options:附加參數(shù)
而ActivityMangagerNitive調(diào)用的是ActivityManagerProxy的startActivity方法,最后調(diào)用mRemote方法呢灶,mRemote是Binder類型,由此可見這里startActivity是通過調(diào)用遠程ActivityManagerService的binder調(diào)用的是遠程的onStransct方法,而ActivityManagerService是ActivityMangagerNitive的子類,onStransct的實現(xiàn)是在ActivityMangagerNitive钉嘹,所以我們進入到ActivityMangagerNitive鸯乃,從ActivityMangagerNitive的onTransact方法可以看出調(diào)用的是子類的startActivity方法,我們知道ActivityManagerNative的子類是ActivityManagerService跋涣。
這里涉級到一個技巧缨睡,我們每個Activity都必須到AndroidManifest.xml里面去注冊否則我們就無法啟動這個Activity,我們是否想到有沒有可能不注冊Activity就能啟動這個Activity呢陈辱?答案是肯定的奖年,我們可以在AndroidManifest.xml里面注冊一個代理的Activity,只要在進入ActivityManagerNative方法后,我們把我們的啟動Activity換成一個在AndroidManifest.xml中己經(jīng)注冊好的代理類Activity沛贪,這樣就可以欺騙系統(tǒng)說陋守,我己經(jīng)注冊了這個Activity了,你不需要拋出找不到Activity的異常鹏浅。
public abstract class ActivityManagerNative extends Binder implements IActivityManager
// 這是遠程ActivityManagerService的onTransact方法
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
// 根據(jù)傳過來的code類型嗅义,我們知道會調(diào)用到進入到下面的case去
case START_ACTIVITY_TRANSACTION:
{
....省略代碼
// 調(diào)用startActivity方法,具體的實現(xiàn)在ActivityManagerService
int result = startActivity(app, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
...省略代碼
return true;
}
}
class ActivityManagerProxy implements IActivityManager
...省略代碼
public int startActivity(...省略參數(shù)) throws RemoteException {
...
// 調(diào)用遠程的transact方法隐砸,帶上START_ACTIVITY_TRANSACTION的code類型
// 并把所有的參數(shù)都帶到遠程去
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
...
return result;
}
...省略代碼
}
}
下面我們分析ActivityManagerService的startActivity方法之碗,startActivity調(diào)用的是startActivityAsUsery方法,startActivity比startActivityAsUsery多出了UserId,有了這個UserId季希,就可以檢查調(diào)用者的權(quán)限褪那。而startActivityAsUser會跳到ActivityStarter的startActivityMayWait方法
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
...省略代碼
@Override
public final int startActivity(...省略參數(shù)) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId());
}
...省略代碼
@Override
public final int startActivityAsUser(...省略參數(shù)) {
...省略代碼
// 跳出ActivityManagerSerivce,進入到ActivityStarter的startActivityMayWait方法
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null);
}
}
下面我們進入到ActivityStarter類,因為ActivityStarter類涉及的方法太多式塌,這里只是會分析幾個重要的調(diào)用:
首先博敬,我們進入到ActivityStarter的startActivityMayWait方法 此方法里面mSupervisor.resolveIntent(intent, resolvedType, userId)會進入到PackageManagerService的resolveIntent方法,此方法是開發(fā)者使用隱式調(diào)用時峰尝,會彈出選擇窗讓用戶自己使擇打開的應(yīng)用
然后偏窝,我們進入到了ActivityStarter的startActivityLocked方法, 此方法大部份是對調(diào)用者的權(quán)限進行驗證武学,看是否調(diào)用者是否有權(quán)限進行操作
然后進入到ActivityStarter的startActivityUnchecked方法祭往,此方法主要是判斷Activity是以什么方式啟動,還有以什么方式入Activity棧, 例如computeLaunchingTaskFlags(); 判斷Activity啟動的以什么方式啟動
然后我們進入到ActivityStack的startActivityLocked方法火窒,這方法主要是設(shè)置Activity的準(zhǔn)備工作己經(jīng)完成
最后由postStartActivityUncheckedProcessing方法發(fā)出通知Activity的啟動工作完成
class ActivityStarter {
final int startActivityMayWait(...省略參數(shù)) {
...省略代碼
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
...省略代碼
// 進入到startActivityLocked方法硼补,此方法主要是檢查Activity啟動的權(quán)限
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
...省略代碼
return res;
}
}
final int startActivityLocked(...省略參數(shù)) {
....省略代碼
//
if (abort) {
if (resultRecord != null) {
resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
RESULT_CANCELED, null);
}
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
ActivityOptions.abort(options);
return START_SUCCESS;
}
try {
err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask);
} finally {
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
return err;
}
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, sume, ActivityOptions options, TaskRecord inTask) {
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor);
// 還是用來初始化啟動標(biāo)志位的
computeLaunchingTaskFlags();
computeSourceStack();
...省略代碼
mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
...省略代碼
return START_SUCCESS;
}
void postStartActivityUncheckedProcessing(
ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
ActivityStack targetStack) {
...省略代碼
// We're waiting for an activity launch to finish, but that activity simply
// brought another activity to front. Let startActivityMayWait() know about
// this, so it waits for the new activity to become visible instead.
if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
}
...省略代碼
}
...省略代碼
}
final class ActivityStack {
...省略代碼
final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
ActivityOptions options) {
...省略代碼
// Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
// tell WindowManager that r is visible even though it is at the back of the stack.
mWindowManager.setAppVisibility(r.appToken, true);
...
}
...
}
下面我們進入到ActivityStackSupervisor源碼,reportTaskToFrontNoLaunch的作用是如果change為true就通知通知ActivityStarter待啟動Activity對應(yīng)的Task移動到了前臺
public final class ActivityStackSupervisor implements DisplayListener {
...省略代碼
void reportTaskToFrontNoLaunch(ActivityRecord r) {
boolean changed = false;
for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
WaitResult w = mWaitingActivityLaunched.remove(i);
if (w.who == null) {
changed = true;
// Set result to START_TASK_TO_FRONT so that startActivityMayWait() knows that
// the starting activity ends up moving another activity to front, and it should
// wait for this new activity to become visible instead.
// Do not modify other fields.
w.result = START_TASK_TO_FRONT;
}
}
if (changed) {
//notifyAll通知ActivityStarter待啟動Activity對應(yīng)的Task移動到了前臺
mService.notifyAll();
}
}
...省略代碼
}
發(fā)送通知后熏矿,就會調(diào)用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法已骇,然后調(diào)ActivityStack的resumeTopActivityUncheckedLocked方法离钝,再調(diào)用ActivityStack的resumeTopActivityInnerLocked,最后進入到ActivityThread的scheduleLaunchActivity方法
前面講過可以啟動一個沒有在AndroidManifest.xml里面注冊過的Activity褪储,只需要用動態(tài)代理的方法卵渴,把H的handleMessage攔截,然后在這里把我們沒有注冊的Activity放回到intent里面就可以實現(xiàn)啟動沒有注冊的Activity
public final class ActivityThread {
public static void main(String[] args) {
...省略代碼
// 下面是啟動UI主線程
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
...
// 發(fā)送啟動Activity的消息
sendMessage(H.LAUNCH_ACTIVITY, r);
}
private class H extends Handler {
...省略代碼
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;、
// 獲取Activity信息
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break乱豆;
...
}
}
...省略代碼
}
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// 初始化WindowManagerService服務(wù)
WindowManagerGlobal.initialize();
// 創(chuàng)建Activity,這里會執(zhí)行Activity的生命周期
Activity a = performLaunchActivity(r, customIntent);
// 如果Activity不為空奖恰,則啟動Activity
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
// The activity manager actually wants this one to start out paused, because it
// needs to be visible but isn't in the foreground. We accomplish this by going
// through the normal startup (because activities expect to go through onResume()
// the first time they run, before their window is displayed), and then pausing it.
// However, in this case we do -not- need to do the full pause cycle (of freezing
// and such) because the activity manager assumes it can just retain the current
// state it has.
performPauseActivityIfNeeded(r, reason);
...
}
} else {
// 找不到需要啟動的Activity報錯
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
}
這里只對Activity的啟動流程分析,沒有對每個方法進行詳情的分析宛裕,有興趣的讀者可以看Android的源碼