Android 元件Activity啟動流程分析
本篇相關流程分析基於Android4.4原始碼。
通常我們啟動一個Activity都是通過startActivity來完成。下面我們分析一下關鍵流程,本篇中以前應用的主執行緒ActivityThread為界限一分為二。
意圖啟動
首先我們使用上下文物件來呼叫startActivity
從圖中Activity的啟動意圖一直經過ContextWrapper,ContextImp,Instrumentation到AMS(ActivityManagerService),再到ActivityStackSupervisor才開始著手解析意圖相關資訊。
在ContextImpl.java中,startActivity呼叫如下:
public void startActivity(Intent intent, Bundle options) {
warnIfCallingFromSystemProcess();
if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
throw new AndroidRuntimeException(
“Calling startActivity() from outside of an Activity ”
+ ” context requires the FLAG_ACTIVITY_NEW_TASK flag.”
+ ” Is this really what you want?”);
}
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity)null, intent, -1, options);
}
主執行緒mMainThread獲取Instrumentation來呼叫execStartActivity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options, UserHandle user) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
……
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mWho : null,
requestCode, 0, null, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
ActivityManagerNative.getDefault()會得到AMS服務,注意AMS繼承於ActivityManagerNative
private static final Singleton gDefault = new Singleton() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService(“activity”);
if (false) {
Log.v(“ActivityManager”, “default service binder = ” + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v(“ActivityManager”, “default service = ” + am);
}
return am;
}
};
static public IActivityManager getDefault() {
return gDefault.get();
}
gDefault本身就是AMS服務的代理端,通過binder與服務端AMS通訊並呼叫startActivity
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode,
startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
}
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
enforceNotIsolatedCaller(“startActivity”);
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, true, “startActivity”, null);
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
null, null, options, userId);
}
AMS中的startActivity最終呼叫到ActivityStackSupervisor.java中的startActivityMayWait
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, String profileFile,
ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
Bundle options, int userId) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
boolean componentSpecified = intent.getComponent() != null;
// Don't modify the client's object!
intent = new Intent(intent);
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
profileFile, profileFd, userId);
synchronized (mService) {
int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = Binder.getCallingPid();
callingUid = Binder.getCallingUid();
} else {
callingPid = callingUid = -1;
}
final ActivityStack stack = getFocusedStack();
stack.mConfigWillChange = config != null
&& mService.mConfiguration.diff(config) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG,
"Starting activity when config will change = " + stack.mConfigWillChange);
final long origId = Binder.clearCallingIdentity();
......
int res = startActivityLocked(caller, intent, resolvedType,
aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
callingPackage, startFlags, options, componentSpecified, null);
......
return res;
}
}
接著進入startActivityLocked,startActivityUncheckedLocked
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity) {
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
......
mService.doPendingActivityLaunchesLocked(false);
err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
if (allPausedActivitiesComplete()) {
// If someone asked to have the keyguard dismissed on the next
// activity start, but we are not actually doing an activity
// switch... just dismiss the keyguard now, because we
// probably want to see whatever is behind it.
dismissKeyguard();
}
return err;
}
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
int launchFlags = intent.getFlags();
......
......
ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
targetStack.mLastPausedActivity = null;
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
mService.setFocusedActivityLocked(r);
return ActivityManager.START_SUCCESS;
}
上述ActivityStatckSupervisor,ActivityStatck之間做了一些轉調進入startSpecificActivityLocked
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity’s application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
從上面可以看到如果當前Activity所屬的Application已經在執行,就走realStartActivityLocked,否則呼叫AMS的來啟動應用程序startProcessLocked(下篇分析)。
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
r.startFreezingScreenLocked(app, 0);
if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
mWindowManager.setAppVisibility(r.appToken, true);
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();
......
mService.updateLruProcessLocked(app, true, null);
mService.updateOomAdjLocked();
final ActivityStack stack = r.task.stack;
try {
......
app.hasShownUi = true;
app.pendingUiClean = true;
if (profileFd != null) {
try {
profileFd = profileFd.dup();
} catch (IOException e) {
if (profileFd != null) {
try {
profileFd.close();
} catch (IOException o) {
}
profileFd = null;
}
}
}
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new Configuration(mService.mConfiguration), r.compat,
app.repProcState, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
......
} catch (RemoteException e) {
if (r.launchFailed) {
// This is the second time we failed -- finish activity
// and give up.
Slog.e(TAG, "Second failure launching "
+ r.intent.getComponent().flattenToShortString()
+ ", giving up", e);
mService.appDiedLocked(app, app.pid, app.thread);
stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
"2nd-crash", false);
return false;
}
// This is the first time we failed -- restart process and
// retry.
app.activities.remove(r);
throw e;
}
......
// Launch the new version setup screen if needed. We do this -after-
// launching the initial activity (that is, home), so that it can have
// a chance to initialize itself while in the background, making the
// switch back to it faster and look better.
if (isFrontStack(stack)) {
mService.startSetupActivityLocked();
}
return true;
}
app.thread.scheduleLaunchActivity此句會將後續工作交給ActivityThread處理。
Activity啟動
ActivityThread接管後流程如下:
從圖上看,ActivityThread收到Activity啟動意圖後,就開始通過ClassLoader的反射機制建立Activity,呼叫onCreate,onResume,attach,addView將window,DecorView,ViewRootImp連線起來構成完整檢視。
首先scheduleLaunchActivity將新的Activity資訊封裝在ActivityClientRecord併發送廣播LAUNCH_ACTIVITY,handler收到訊息後會進入handleLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
......
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
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.
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
// We need to keep around the original state, in case
// we need to be created again. But we only do this
// for pre-Honeycomb apps, which always save their state
// when pausing, so we can not have them save their state
// when restarting from a paused state. For HC and later,
// we want to (and can) let the state be saved as the normal
// part of stopping the activity.
if (r.isPreHoneycomb()) {
r.state = oldState;
}
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to pause activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
r.paused = true;
}
} else {
// 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);
} catch (RemoteException ex) {
// Ignore
}
}
}
performLaunchActivity會完成裝置上下文的建立,標題欄設定,主題的設定,onCreate,onStart
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
……
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
......
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
mInstrumentation.callActivityOnCreate(activity, r.state);
......
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
......
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
......
}
return activity;
}
主要的完成了Activity的建立,在ViewGroup新增各個子檢視,以及PhoneWind,DecorView的繫結連線。
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
boolean reallyResume) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
final Activity a = r.activity;
......
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(
TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
// Get rid of anything left hanging around.
cleanUpPendingRemoveWindows(r);
// The window is now visible if it has been added, we are not
// simply finishing, and we are not starting another activity.
if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
if (r.newConfig != null) {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
+ r.activityInfo.name + " with newConfig " + r.newConfig);
performConfigurationChanged(r.activity, r.newConfig);
freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
r.newConfig = null;
}
if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
+ isForward);
WindowManager.LayoutParams l = r.window.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
!= forwardBit) {
l.softInputMode = (l.softInputMode
& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
| forwardBit;
if (r.activity.mVisibleFromClient) {
ViewManager wm = a.getWindowManager();
View decor = r.window.getDecorView();
wm.updateViewLayout(decor, l);
}
}
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
......
r.onlyLocalRequest = false;
.....
} else {
......
}
}
handleResumeActivity中,performResumeActivity主要是通過Instrumentation呼叫Activity的onResume;接著獲取PhoneWindow,DecorView,WindowManagerImp,最後通過WindowManagerImp.addView
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
public void addView(View view, ViewGroup.LayoutParams params) {
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
WondowManagerGlobal接管
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
......
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// Start watching for system property changes.
if (mSystemPropertyUpdater == null) {
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
for (int i = mRoots.size() - 1; i >= 0; --i) {
mRoots.get(i).loadSystemProperties();
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
int index = findViewLocked(view, false);
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
mRoots.get(index).doDie();
} else {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
// The previous removeView() had not completed executing. Now it has.
}
// If this is a panel window, then find the window it is being
// attached to for future reference.
if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
final int count = mViews.size();
for (int i = 0; i < count; i++) {
if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
panelParentView = mViews.get(i);
}
}
}
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true);
}
}
throw e;
}
}
addView時,將view,ViewRootImo, WindowManager.LayoutParams 儲存至陣列列表中,最後ViewRootImp.setView 新增該檢視,並將view也新增至PhoneFallBackEventHandler中,通過InputChannel 和IMS
建立按鍵處理通道。
相關推薦
Android 元件Activity啟動流程分析
本篇相關流程分析基於Android4.4原始碼。 通常我們啟動一個Activity都是通過startActivity來完成。下面我們分析一下關鍵流程,本篇中以前應用的主執行緒ActivityThread為界限一分為二。 意圖啟動 首先我們使用上下文物件來
Activity啟動流程分析(基於android 5.1)
最近由於工作需要,需要深入瞭解AMS的內部實現。說老實話,雖然已經經過了幾輪重構,AMS的程式碼還是又臭又長。。。 萬事開頭難,先找個入口開始看吧。當從Launcher介面點選啟動一個app時,會啟動一個新的activity。所以就從startActivity()看起,研究
Android Activity啟動流程分析
概述 Activity作為Android的四大元件之一,Android主要的介面組成部分,用於直接跟使用者進行互動操作,在面試中與Activity相關的知識也是經常被問到,如果你面試的高階崗位,那麼對Activity的啟動和繪製流程就必須的熟悉,本文將從Act
Android9.0 Activity啟動流程分析(二)
文章目錄 1、ActivityThread的main函式 2. AMS的attachApplication函式 2.1 Part-I 2.2 Part-II 2.2.1 ApplicationThread的bindApp
Android9.0 Activity啟動流程分析(一)
1、ActivityRecord、TaskRecord、ActivityStack和ActivityDisplay介紹 本篇文章是基於Android refs/tags/android-9.0.0_r8分支的程式碼進行分析的 在分析Activity啟動的原始碼之前先介紹一下Act
Android WifiService的啟動流程分析
轉於: http://blog.csdn.net/lilian0118/article/details/21964423 最近在學習Android WiFi framework的相關知識,這裡總結以下。WiFi framework的內容大致可以分為以下幾個模組: 1
android 面試Activity啟動流程
android 面試題之Activity的啟動流程 面試中高階的時候,很多公司都會問對Activity的啟動流程瞭解嗎?這時候內心真是一萬隻草泥馬奔騰而過,都沒準備說啥啊!市場上對Activity啟動這塊分析的文章很多,但是面試過程中簡短的描述就需要很熟悉原始
Android4.4 Activity啟動流程分析
$ adb logcat -v time -s ActivityManager --------- beginning of /dev/log/main --------- beginning of /dev/log/system 07-01 08:35:20.039 V/ActivityManager
Android之Activity啟動流程詳解(基於api28)
### 前言 Activity作為Android四大元件之一,他的啟動絕對沒有那麼簡單。這裡涉及到了系統服務程序,啟動過程細節很多,這裡我只展示主體流程。activity的啟動流程隨著版本的更替,程式碼細節一直在進行更改,每次都會有很大的修改,如android5.0 android8.0。我這裡的版本是基於
【Android】原始碼分析 - Activity啟動流程
啟動Activity的方式 Activity有2種啟動的方式,一種是在Launcher介面點選應用的圖示、另一種是在應用中通過Intent進行跳轉。我們主要介紹與後者相關的啟動流程。 Intent intent = new Intent(this, TestActivity
Android 元件系列 -- Activity 啟動流程(9.0)
在學習完Android應用程式啟動過程原始碼分析,針對最新Android9.0的程式碼,以相應的順序再次學習。在9.0的版本中對於Activity的啟動流程上並沒有太大的變化,但是在程式碼層面,改動的卻很多。 流程概覽 以Launcher啟動APP為例: Lau
Android 外掛化分析(3)- Activity啟動流程
在真正分析外掛化技術前,我們必須瞭解一些必要的關於Android四大元件的相關知識。 以Activity為例,我們需要了解Activity啟動過程,才能有效的進行Hook實現外掛化。 以Android 8.1為例 我們啟動一個Activity通常會使用startActi
(Android 9.0)Activity啟動流程原始碼分析
前言 熟悉Activity的啟動流程和執行原理是一個合格的應用開發人員所應該具備的基本素質,其重要程度就
Android 虛擬機器簡單介紹——ART、Dalvik、啟動流程分析
Android 虛擬機器方面的知識,我是通過《深入理解 Android 核心設計思想》來學習的,內容特別多(只有一章,但有 160 頁),但感覺和 Android 開發有些偏了,因此很多內容都沒有認真去看,比如 EFL 格式等,這裡只是選取了一些感覺比較重要的做
[譯]Android Application啟動流程分析
譯者注: 原文分成兩個部分, 連結如下: http://multi-core-dump.blogspot.com/2010/04/android-application-launch.html http://multi-core-dump.blogspot.com/2010/04/
Activity啟動流程原始碼分析(應用中)
在移動應用開發中,Android四大元件之一Activity是最常用的。很多介面,如:閃屏、主介面、次功能介面等都需要Activity來作為主要的載體;介面與介面之間,即不同的Activity之間也都存在跳轉切換,弄懂這其中跳轉切換原理,將有助於我們更好的理解A
Android 7.0系統啟動流程分析
隨著Android版本的升級,aosp專案中的程式碼也有了些變化,本文基於Android 7.0分析Android系統啟動流程.當我們按下電源鍵後,整個Android裝置大體經過了一下過程: 今天我們只想來分析init程序及其後的過程,也就是下圖所示部分:
Android N Wi-Fi 啟動流程分析
當我們在手機的setting中開啟wifi開關時,首先是wifisetting中的oncreate將載入佈局檔案。 @Override public void onCreate(Bundle icicle) { super.on
Android 7.0應用冷啟動流程分析
最近在為自己Moto G定製Rom,順便重新讀了一遍Android 7.0的相關原始碼,特此記錄當做筆記. 在開始正文之前,首先要明白冷啟動和熱啟動.所謂冷啟動就是啟動該應用時,後臺沒有該應用的程序,此時系統會建立一個程序分配給它(AMS通過Socket和Zy
Android Application啟動流程分析
作者曾經在高通的Android效能組工作, 主要工作是優化Android Application的啟動時間. 1, App基礎理論 要想優化App啟動時間, 第一步就是了解App啟動程序的工作原理. 有幾個基礎理論: Android Application與其他移