一、APK 安裝流程詳解
1.1 安裝步驟全解析
APK 的安裝可總結(jié)為以下 7 個(gè)關(guān)鍵步驟,無論 APK 是通過 adb 安裝(存儲于 PC 磁盤)還是通過應(yīng)用市場安裝(存儲于設(shè)備),流程一致:
步驟 1:臨時(shí)拷貝
- APK 首先被拷貝到
/data/app/xxx.tmp目錄下; - 其中
xxx是一個(gè)隨機(jī)生成的字符串。
步驟 2:驗(yàn)證與重命名
- 經(jīng)過重重驗(yàn)證與校驗(yàn)(包括簽名、版本號等);
-
/data/app/xxx.tmp目錄會被重命名為:/data/app/[randomStrA]/[packageName]-[randomStrB] - 被拷貝的 APK 最終路徑為:
/data/app/[randomStrA]/[packageName]-[randomStrB]/base.apk - 同時(shí)會為 APK 生成一個(gè)唯一的 ID,又稱 appid。
步驟 3:Manifest 解析與 PMS 注冊
- 解析 APK 的
AndroidManifest.xml中的內(nèi)容為ParsedPackage; -
ParsedPackage中的權(quán)限等信息經(jīng)過驗(yàn)證通過后,傳遞給 PMS(PackageManagerService); - 這樣其他系統(tǒng)服務(wù)(如
ActivityManagerService)就可以從 PMS 獲取剛安裝 APK 的信息。
步驟 4:持久化安裝信息
- 剛安裝的 APK 的安裝信息(如包名、版本、簽名證書、安裝時(shí)間等)會存儲到
PackageSetting; -
PackageSetting會傳遞給Settings; -
Settings會將其持久化到packages.xml文件中。
步驟 5:創(chuàng)建 App Data 根目錄
- 創(chuàng)建 app data 根目錄,該目錄是 APK 運(yùn)行期間數(shù)據(jù)存儲的根目錄;
- 權(quán)限控制:只有當(dāng)前 APK 程序擁有該目錄的讀、寫、執(zhí)行權(quán)限,其他應(yīng)用沒有任何權(quán)限。
步驟 6:DEX 優(yōu)化(可選但推薦)
- 對 APK 的 DEX 文件進(jìn)行優(yōu)化(如生成 OAT 文件);
- 注意:優(yōu)化即使不成功也不影響 APK 的安裝;
- DEX 優(yōu)化可顯著提升 App 運(yùn)行性能。
步驟 7:發(fā)送安裝成功廣播
- 系統(tǒng)發(fā)送
ACTION_PACKAGE_ADDED等安裝成功廣播,通知其他組件。
【補(bǔ)充】
安裝耗時(shí)主要取決于 APK 大小和內(nèi)容復(fù)雜度。APK 越大、包含的.so庫越多,安裝時(shí)間越長。主要耗時(shí)體現(xiàn)在:
- 拷貝 APK 文件;
- 提取 native libraries(
.so文件);- DEX 優(yōu)化(如 ART 編譯)。
1.2 參考資料與圖示

系統(tǒng)啟動流程

Android啟動流程

啟動流程圖

啟動流程圖

Framework源碼解析
【補(bǔ)充】
上述圖片雖標(biāo)題為“啟動流程”,但實(shí)際展示了 Android 系統(tǒng)從 Zygote 到 AMS/PMS 初始化的完整鏈路,與 APK 安裝密切相關(guān),因安裝過程依賴 PMS 和 Installer 服務(wù)。
二、Activity 啟動流程(Framework 層調(diào)用鏈)
2.1 啟動調(diào)用棧(自上而下)
Activity#startActivity
Activity#startActivityForResult
Instrumentation#execStartActivity()
ActivityManagerService#startActivity()
ActivityTaskManagerService#startActivity()
ActivityTaskManagerService#startActivityAsUser()
ActivityStarter#execute()
ActivityStarter#startActivityMayWait()
ActivityStarter#startActivity()
ActivityStarter#startActivityUnchecked()
RootActivityContainer#startActivityLocked()
ActivityStack#resumeTopActivityUncheckedLocked()
ActivityStack#resumeTopActivityInnerLocked()
【補(bǔ)充】
自 Android 10 起,Activity 管理職責(zé)從ActivityManagerService(AMS)部分遷移到新的ActivityTaskManagerService(ATMS),以支持更復(fù)雜的多窗口和分屏場景。
三、Task 與回退棧機(jī)制
3.1 Task 的基本概念
- 當(dāng)用戶點(diǎn)擊桌面上的 App 圖標(biāo)時(shí),App 的默認(rèn) Activity(即配置了
MAIN + LAUNCHERintent-filter 的 Activity)會被啟動; - 該 Activity 會被放入系統(tǒng)剛創(chuàng)建的一個(gè) Task 中。
3.2 最近任務(wù)切換的本質(zhì)
- 用戶通過“最近任務(wù)鍵”在多個(gè) App 之間切換,實(shí)質(zhì)是在多個(gè) Task 之間切換;
- 每個(gè) Task 都有一個(gè)自己的回退棧(back stack),按順序記錄用戶打開的每個(gè) Activity;
- 按返回鍵時(shí),系統(tǒng)按倒序依次關(guān)閉這些 Activity。
3.3 Task 的生命周期與“殘影”
- 當(dāng)回退棧中最后一個(gè) Activity 被關(guān)閉,Task 的生命結(jié)束;
- 但該 Task 不會立即從最近任務(wù)列表消失;
- 系統(tǒng)保留一個(gè)“殘影”供用戶“切回去”;
- 此時(shí)“切回去”實(shí)為重新啟動 App,因?yàn)樵?Task 已銷毀;
- 結(jié)論:在最近任務(wù)里看見的 Task,未必還活著。
3.4 Task 的疊加行為
- 不僅 Activity 可在 Task 內(nèi)部疊成棧,不同的 Task 之間也可以疊加;
- 限制:Task 的疊加只適用于前臺 Task;
- 一旦前臺 Task 進(jìn)入后臺(如按 Home 鍵或最近任務(wù)鍵),疊加的多個(gè) Task 會立即被拆開。
四、Activity LaunchMode 詳解
4.1 Standard(默認(rèn)模式)
- 每次啟動都會創(chuàng)建新實(shí)例,并加入當(dāng)前 Task 棧頂。
4.2 SingleTop
- 行為與 Standard 類似,唯一區(qū)別:
- 如果棧頂?shù)?Activity 恰好是要啟動的 Activity,則不新建,而是調(diào)用其
onNewIntent()方法。
- 如果棧頂?shù)?Activity 恰好是要啟動的 Activity,則不新建,而是調(diào)用其
4.3 SingleTask
-
任務(wù)棧中唯一:
- 啟動同一個(gè) Activity 時(shí),會清除其上方的所有 Activity;
- 常用于應(yīng)用首頁。
-
全局唯一性保證:
- 保證“只有一個(gè) Task 里有這個(gè) Activity”;
- 且“這個(gè) Task 里最多只有一個(gè)這個(gè) Activity”;
- 因此,盡管名為
singleTask,實(shí)質(zhì)上限制了該 Activity 在全局只有一個(gè)對象。
-
跨 App 行為:
- 當(dāng)被其他 App 啟動時(shí),不會進(jìn)入啟動者的 Task;
- 而是在屬于它自己的 Task 中創(chuàng)建,并置于棧頂;
- 然后將整個(gè) Task 被系統(tǒng)標(biāo)記為處于前臺,也可以理解為壓在啟動者 Task 之上。
4.4 SingleInstance
-
系統(tǒng)唯一:
- 整個(gè)系統(tǒng)只有一個(gè)任務(wù)棧,且只有一個(gè) Activity 實(shí)例;
- 常用于來電顯示等全局獨(dú)占場景。
-
啟動行為:
- 啟動新 Activity 時(shí),由于
singleInstance限制,新 Activity 不會進(jìn)入當(dāng)前 Task; - 而是被放入另一個(gè)獨(dú)立的 Task,并隨該 Task 一起被系統(tǒng)標(biāo)記為處于前臺。
- 啟動新 Activity 時(shí),由于
-
返回鍵行為差異(vs SingleTask):
-
singleInstance:按返回鍵會直接回到原先的 App; -
singleTask:在自己的 App 內(nèi)回退。
-
-
桌面啟動行為差異:
-
singleInstance:從桌面再次點(diǎn)開 App 時(shí),看不到該 Activity(它仍在后臺某個(gè) Task 中);- 并未被殺死,再次啟動會回到前臺,并收到
onNewIntent()回調(diào)。
- 并未被殺死,再次啟動會回到前臺,并收到
-
standard/singleTop:Activity 依然在棧頂可見。
-
【補(bǔ)充】
singleInstance的 Task 不會出現(xiàn)在最近任務(wù)列表中(或被同 affinity 的其他 Task 排擠),因此用戶“看不見”它,但它依然存活。
五、taskAffinity 機(jī)制
5.1 默認(rèn)行為
- 一個(gè) App 默認(rèn)只能有一個(gè) Task 顯示在最近任務(wù)列表里;
- 用于甄別“唯一性”的并非 App 本身,而是
taskAffinity。
5.2 taskAffinity 的取值規(guī)則
- 默認(rèn)取自
Application的taskAffinity; -
Application的taskAffinity默認(rèn)為 App 的包名。
5.3 Task 的 taskAffinity
- 每個(gè) Task 的
taskAffinity取自其棧底 Activity 的taskAffinity。
5.4 singleTask 與 taskAffinity 的交互
- 若新 Activity 配置為
singleTask,Android 會檢查:- 新 Activity 的
taskAffinity與當(dāng)前 Task 的taskAffinity是否相同; - 若相同 → 繼續(xù)入棧;
- 若不同 → 進(jìn)入與其
taskAffinity相同的現(xiàn)有 Task,或創(chuàng)建新 Task。
- 新 Activity 的
5.5 最近任務(wù)顯示規(guī)則
- 不同的 Task 會并列展示在最近任務(wù)列表中;
-
前提:它們的
taskAffinity必須不同; - 同一個(gè)
taskAffinity可創(chuàng)建多個(gè) Task,但最多只有一個(gè)能顯示在最近任務(wù)列表; - 這解釋了為何
singleInstanceActivity 會從最近任務(wù)中“消失”——被同affinity的其他 Task 搶占。 - 不同 Task 之間:是 “并行存在于系統(tǒng)任務(wù)列表” 的關(guān)系,而非 “堆疊”,系統(tǒng)會記錄哪個(gè) Task 處于前臺。
六、allowTaskReparenting 機(jī)制(Task Reparenting)
6.1 默認(rèn)行為限制
- Activity 默認(rèn)只歸屬于一個(gè) Task,不會在多個(gè) Task 間跳轉(zhuǎn)。
6.2 啟用 allowTaskReparenting
- 若將 Activity 的
android:allowTaskReparenting="true":- 當(dāng)從短信 App 打開郵件編寫 Activity 時(shí),它會進(jìn)入短信 App 的 Task;
- 但當(dāng)用戶稍后從桌面打開郵件 App 時(shí),該 Activity 會被自動挪回郵件 App 的 Task,置于棧頂;
- 切回短信 App 時(shí),該 Activity 已消失。
6.3 與 singleTask 的對比優(yōu)勢
- 無感知切換:沒有 Task 切換的夸張入場動畫;
-
回退路徑連續(xù):用戶切后臺再回來,不會像
singleTask那樣被切斷回退路徑。
6.4 兼容性問題
- 在 Android 9 和 10 上該屬性失效;
- 在 Android 11 上被修復(fù),恢復(fù)正常行為。
七、LaunchMode 使用場景總結(jié)
| 模式 | 主要用途 |
|---|---|
standard / singleTop
|
App 內(nèi)部常規(guī)跳轉(zhuǎn) |
singleInstance |
開放給其他 App 使用的共享 Activity(如來電、支付頁) |
singleTask |
兼容派:既用于內(nèi)部(如首頁),也用于外部共享 |
【核心理解】
理解 launchMode 需從多應(yīng)用間的 Activity 跳轉(zhuǎn)入手。在一個(gè)應(yīng)用內(nèi)和多個(gè)應(yīng)用間,它們表現(xiàn)不同,但本質(zhì)統(tǒng)一:
- Task 的唯一標(biāo)識是
affinity;affinity取決于棧底 Activity;- 系統(tǒng)通過標(biāo)記最近前臺應(yīng)用來處理Task的切換和回退,從感官上實(shí)現(xiàn)
Task 內(nèi)部可以疊加 Task,但一旦進(jìn)入后臺會拆開;- Task 間的切換會有過場動畫。
八、擴(kuò)展參考資料(原樣保留)
- Activity 的啟動模式
- ActivityRecord、TaskRecord、ActivityStack以及Activity啟動模式詳解
- Intent.addFlags() 啟動Activity的20種flags全解析
- Activity finish后延遲10s關(guān)閉
- Android啟動
- APK安裝過程 完全解析!
- Android9.0 Activity啟動原理差異解析
- APP的回收和重啟機(jī)制
- ActivityRecord、TaskRecord、ActivityStack、ActivityDisplay、ActivityStackSupervisor
- Ams管理Activity啟動
- APP回收和重啟機(jī)制