天天看点

Android6.0 AMS启动Activity(五) 在新进程中启动Activity



前面我们在分析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);
    }
           

继续阅读