前面我们在分析Activity启动过程的时候,看到同一个应用程序的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);
}