Android6.0 AMS 新程序中啟動Activity
看到同一個應用程式的Activity一般都是在同一個程序中啟動,事實上,Activity也可以像Service一樣在新的程序中啟動,這樣,一個應用程式就可以跨越好幾個程序了,本文就分析一下在新的程序中啟動Activity的方法和過程。
在Android系統中,每一個應用程式都是由一些Activity和Service組成的,一般Service執行在獨立的程序中,而Activity有可能執行在同一個程序中,也有可能執行在不同的程序中。在前面我們已經介紹了Android應用程式在Launcher桌面啟動一個Activity需要啟動一個程序,也介紹了在程序內部啟動Activity過程(startActivity)。而現在,我們就來看一下同一個Android應用程式如何在新的程序中啟動新的Activity。
要做到這個其實很簡單,只需要在AndroidManifest.xml中將主Activity和要啟動的Activity的android:process屬性設定為不同的
- <?xmlversion="1.0"encoding="utf-8"?>
- <manifestxmlns:android="http://schemas.android.com/apk/res/android"
- package="shy.luo.task"
- android:versionCode="1"
- android:versionName="1.0">
- <applicationandroid:icon
- <activityandroid:name=".MainActivity"
- android:label="@string/app_name">
- android:process=":com.example.process.main"
- <intent-filter>
- <actionandroid:name="android.intent.action.MAIN"
- <categoryandroid:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- <activityandroid:name=".SubActivity"
- android:label="@string/sub_activity"
- android:process=":shy.luo.process.sub">
- <intent-filter>
- <actionandroid:name="com.example.process.subactivity"/>
- <categoryandroid:name="android.intent.category.DEFAULT"/>
- </intent-filter>
- </activity>
- </application>
- </manifest>
同一個應用程式的Activity元件都是執行在同一個程序中,但是,如果Activity配置了android:process這個屬性,那麼,它就會執行在自己的程序中。如果android:process屬性的值以":"開頭,則表示這個程序是私有的;如果android:process屬性的值以小寫字母開頭,則表示這是一個全域性程序,允許其它應用程式元件也在這個程序中執行。
因此,這裡我們以":"開頭,表示建立的是私有的程序。事實上,這裡我們不要前面的":"也是可以的,但是必須保證這個屬性性字串內至少有一個"."字元。
具體解析AndroidManifest.xml會在安裝apk的時候在PKMS呼叫PackageParser的parseBaseApplication來解析。具體程式碼我們會在後續部落格(專門講PKMS安裝apk)中再分析。
這樣processName不一樣之後,在AMS啟動一個Activity時開啟一個程序。當再啟動一個Activity的時候,因為processName不一樣,發現沒有程序的processName是這個name。所以就要再起一個程序,具體程式碼我們之前部落格也分析過,是在ActivityStackSupervisor的startSpecificActivityLocked函式中,發現沒有這個processName的程序後。會呼叫mService.startProcessLocked函式重啟啟動一個程序,也會新建一個ProcessRecord儲存這個程序的資訊。
- 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, r.info.applicationInfo.versionCode,
- 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);
- }