看到同一个应用程序的Activity一般都是在同一个进程中启动,事实上,Activity也可以像Service一样在新的进程中启动,这样,一个应用程序就可以跨越好几个进程了,本文就分析一下在新的进程中启动Activity的方法和过程。
在Android系统中,每一个应用程序都是由一些Activity和Service组成的,一般Service运行在独立的进程中,而Activity有可能运行在同一个进程中,也有可能运行在不同的进程中。在前面我们已经介绍了Android应用程序在Launcher桌面启动一个Activity需要启动一个进程,也介绍了在进程内部启动Activity过程(startActivity)。而现在,我们就来看一下同一个Android应用程序如何在新的进程中启动新的Activity。
要做到这个其实很简单,只需要在AndroidManifest.xml中将主Activity和要启动的Activity的android:process属性设置为不同的
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="shy.luo.task"
- android:versionCode="1"
- android:versionName="1.0">
- <application android:icon="@drawable/icon" android:label="@string/app_name">
- <activity android:name=".MainActivity"
- android:label="@string/app_name">
- android:process=":com.example.process.main"
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <activity android:name=".SubActivity"
- android:label="@string/sub_activity"
- android:process=":shy.luo.process.sub">
- <intent-filter>
- <action android:name="com.example.process.subactivity"/>
- <category android: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);
- }