一诊胞、Activity的啟動過程
ActivityManagerService
:activity的啟動以及生命周期都統(tǒng)一由ActivityManagerService管理履怯,而ActivityManagerService處于SystemServer進程中屹蚊,應(yīng)用程序進程通過Binder機制與SystemServer進程進行通信霹疫。ActivityManagerProxy
:是ActivityManagerService在客戶端的代理,客戶端通過ActivityManageProxy間接調(diào)用ActivityManagerService卵牍。ActivityThread
:應(yīng)用程序的主線程ActivityThread缠导,也是應(yīng)用程序的入口;消息循環(huán)機制的創(chuàng)建胀屿、初始化信息等都在ActivityThread中完成塘揣。ApplicationThread
:用來實現(xiàn)ActivityManagerService與ActivityThread之間的交互。在ActivityManagerService需要管理相關(guān)Application中的Activity的生命周期時宿崭,通過ApplicationThread的代理對象與ActivityThread通訊亲铡。ApplicationThreadProxy
:是ApplicationThread在服務(wù)器端的代理,負(fù)責(zé)和客戶端的ApplicationThread通訊。AMS就是通過該代理與ActivityThread進行通信的奖蔓。Instrumentation
:每一個應(yīng)用程序只有一個Instrumentation對象赞草,每個Activity內(nèi)都有一個對該對象的引用。Instrumentation可以理解為應(yīng)用進程的管家吆鹤,ActivityThread要創(chuàng)建或暫停某個Activity時厨疙,都需要通過Instrumentation來進行具體的操作。
1.1檀头、Launcher請求AMS階段
1.2轰异、AMS到ApplicationThread階段
1.3、ApplicationThread到Activity階段
二、判斷Activity是否注冊
在哪兒判斷Activity是否在AndroidManifest.xml里面注冊的?
首先沒有在AndroidManifest.xml注冊节值,報錯是什么樣子的
- 我們看
Instrumentation
的execStartActivity
方法
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
ActivityResult result = null;
if (am.ignoreMatchingSpecificIntents()) {
result = am.onStartActivity(intent);
}
if (result != null) {
am.mHits++;
return result;
} else if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData(who);
intent.prepareToLeaveProcess(who);
//1.通過IActivityManager調(diào)用我們執(zhí)行AMS的startActivity方法,并返回執(zhí)行結(jié)果
int result = ActivityTaskManager.getService().startActivity(whoThread,
who.getBasePackageName(), who.getAttributionTag(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()), token, target,
requestCode, 0, null, options);
//2. 檢查結(jié)果
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
接下來看checkStartActivityResult
方法
public static void checkStartActivityResult(int res, Object intent) {
if (!ActivityManager.isStartResultFatalError(res)) {
return;
}
switch (res) {
case ActivityManager.START_INTENT_NOT_RESOLVED:
case ActivityManager.START_CLASS_NOT_FOUND:
//3. 這里我們找到了報錯的地方牙肝,原來是res結(jié)果為START_INTENT_NOT_RESOLVED,
//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);
case ActivityManager.START_PERMISSION_DENIED:
throw new SecurityException("Not allowed to start activity "
+ intent);
case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
throw new AndroidRuntimeException(
"FORWARD_RESULT_FLAG used while also requesting a result");
case ActivityManager.START_NOT_ACTIVITY:
throw new IllegalArgumentException(
"PendingIntent is not an activity");
case ActivityManager.START_NOT_VOICE_COMPATIBLE:
throw new SecurityException(
"Starting under voice control not allowed for: " + intent);
case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
throw new IllegalStateException(
"Session calling startVoiceActivity does not match active session");
case ActivityManager.START_VOICE_HIDDEN_SESSION:
throw new IllegalStateException(
"Cannot start voice activity on a hidden session");
case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
throw new IllegalStateException(
"Session calling startAssistantActivity does not match active session");
case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
throw new IllegalStateException(
"Cannot start assistant activity on a hidden session");
case ActivityManager.START_CANCELED:
throw new AndroidRuntimeException("Activity could not be started for "
+ intent);
default:
throw new AndroidRuntimeException("Unknown error code "
+ res + " when starting " + intent);
}
}
private final void validateNotAppThread() {
if (Looper.myLooper() == Looper.getMainLooper()) {
throw new RuntimeException(
"This method can not be called from the main application thread");
}
}