1. 程式人生 > >Android6.0 AMS 新程序中啟動Activity

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屬性設定為不同的

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <manifestxmlns:android="http://schemas.android.com/apk/res/android"
  3.     package="shy.luo.task"
  4.     android:versionCode="1"
  5.     android:versionName="1.0">
  6.     <applicationandroid:icon
    ="@drawable/icon"android:label="@string/app_name">
  7.         <activityandroid:name=".MainActivity"
  8.                   android:label="@string/app_name">
  9.                   android:process=":com.example.process.main"
  10.             <intent-filter>
  11.                 <actionandroid:name="android.intent.action.MAIN"
    />
  12.                 <categoryandroid:name="android.intent.category.LAUNCHER"/>
  13.             </intent-filter>
  14.         </activity>
  15.         <activityandroid:name=".SubActivity"
  16.                   android:label="@string/sub_activity"
  17.                   android:process=":shy.luo.process.sub">
  18.             <intent-filter>
  19.                 <actionandroid:name="com.example.process.subactivity"/>
  20.                 <categoryandroid:name="android.intent.category.DEFAULT"/>
  21.             </intent-filter>
  22.         </activity>
  23.     </application>
  24. </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儲存這個程序的資訊。

  1. void startSpecificActivityLocked(ActivityRecord r,  
  2.         boolean andResume, boolean checkConfig) {  
  3.     // Is this activity's application already running?
  4.     ProcessRecord app = mService.getProcessRecordLocked(r.processName,  
  5.             r.info.applicationInfo.uid, true);  
  6.     r.task.stack.setLaunchTime(r);  
  7.     if (app != null && app.thread != null) {  
  8.         try {  
  9.             if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0  
  10.                     || !"android".equals(r.info.packageName)) {  
  11.                 // Don't add this if it is a platform component that is marked
  12.                 // to run in multiple processes, because this is actually
  13.                 // part of the framework so doesn't make sense to track as a
  14.                 // separate apk in the process.
  15.                 app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,  
  16.                         mService.mProcessStats);  
  17.             }  
  18.             realStartActivityLocked(r, app, andResume, checkConfig);  
  19.             return;  
  20.         } catch (RemoteException e) {  
  21.             Slog.w(TAG, "Exception when starting activity "
  22.                     + r.intent.getComponent().flattenToShortString(), e);  
  23.         }  
  24.         // If a dead object exception was thrown -- fall through to
  25.         // restart the application.
  26.     }  
  27.     mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,  
  28.             "activity", r.intent.getComponent(), falsefalsetrue);