美文网首页
app启动流程

app启动流程

作者: 有心人2021 | 来源:发表于2021-05-28 17:29 被阅读0次

    前言
    AMS(ActivityManagerService)的启动是在SystemServer进程中启动的,它的职责是用于和所有APP的四大组件进行通信,Activity的启动过程就是APP端与AMS端进行通信,首先理解的一点是APP端与AMS是在两个不同的进程中,因此APP端与AMS是通过跨进程通信的。

    从Launcher启动APP
    Launcher就是指手机的屏幕,同时它也是一个APP,只不过这是由制造商开发的,手指点击屏幕的某个APP,这时APP启动并打开首页的界面,这一系列操作需要和AMS进行通信才能完成,APP安装(启动)时,PackageManagerService从APK包的AndroidManifest文件中读取四大组件的信息并保存下来。

    下图是Launcher与AMS的通信时序图:

    image.png

    Launcher与APP是在两个不同的进程中,他们之间的通信是通过Binder完成的,点击Launcher上的某个APP,这时会调用Launcher的startActivitySafely方法。

    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
        ...
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//1
        ...
        startActivity(intent, optsBundle);//2
        ...
    }
    

    上面代码我省略了一些不太重要的,重点看上面两行代码,第一行给intent设置Flag为Intent.FLAG_ACTIVITY_NEW_TASK,Activity会在新的任务栈中启动,第二行代码调用startActivity方法,很简单,就是启动APP中的Activity。

    最终会调用Activity的startActivity方法,Intent中携带的就是需要启动的APP的Activity信息。startActivity方法最终会调用startActivityForResult方法,代码如下:

    @Override
    public void startActivity(Intent intent) {
       this.startActivity(intent, null);
    }
    
    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
       if (options != null) {
           startActivityForResult(intent, -1, options);
       } else {
           // Note we want to go through this call for compatibility with
           // applications that may have overridden the method.
           startActivityForResult(intent, -1);
       }
    }
    
    
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                                      @Nullable Bundle options) {
       ...
       Instrumentation.ActivityResult ar =
               mInstrumentation.execStartActivity(
                       this, mMainThread.getApplicationThread(), mToken, this,
                       intent, requestCode, options);
       ...
    }
    

    可以结合as进android源码根治查看
    Activity内部会保持一个对Instrumentation的引用,Instrumentation主要用来监控应用程序和系统的交互,在startActivityForResult方法中会调用Instrumentation的execStartActivity方法,在execStartActivity方法的第二个参数中,可以看到一个mMainThread的变量,这是一个ActivityThread类型的变量,ActivityThread就是主线程,也就是我们平常所说的UI线程,它是在APP启动时创建的,代表APP应用程序,ActivityThread里面有个main函数,是APP启动时的入口。

    execStartActivity方法传递了两个很重要的参数

    1. mMainThread.getApplicationThread(Binder对象)将Launcher所在的进程传递了过去,这样AMS知道是哪个进程;
    2. 还有一个比较重要的是mToken,它是Binder对象,代表Launcher这个Activity也通过Instrumentation传给AMS,AMS查询时,就知道谁向AMS发起了请求。
    Instrumentation的execStartActivity代码如下:
    
    public Instrumentation.ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
       ...
        try {
            ...
            int result = ActivityManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);
            ...
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
    

    这里通过ActivityManager的getService方法来获取AMS的代理对象(Android 7.0是通过ActivityManagerNative的getDefault来获取AMS的代理对象),返回一个类型为IActivityManager,IActivityManager为核心类,是AIDL文件的接口,可以通过里面定义的接口和AMS进程进行跨进程通讯,IActivityManager是一个接口,内部定义了四大组件的生命周期,

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
    
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
    

    Singleton是一个单例类,内部通过ServiceManager取出一个activity的对象,通过IActivityManager.Stub.asInterface将它包装成一个ActivityManagerProxy对象(AMP),IActivityManager.Stub.asInterface这段代码是不是很熟悉,就是AIDL远程代理,这里获取到的是AMS的代理对象。

    AMP告诉AMS启动哪个APP,并且启动的是哪个Activity,AMS会检查APP中的AndroidManifest文件,看看是否存在要启动的Activity,如果不存在,就会抛出一个Activity not found的错误。AMS检查到启动的Activity存在,这时会告诉Launcher:“我要启动Activity了”,Launcher会将它所在的进程传给AMS,AMS会将它保存为一个ActivityRecord对象,这个对象里面有一个ApplicationThreadProxy,是一个Binder代理,AMS想要发送消息给Launcher,可以通过ApplicationThreadProxy(ATP)来发送消息,ATP是APP端ApplicationThread(APT)的代理对象,用于AMS与APP端的通信。

    既然AMS知道了启动的Activity,接下来就应该启动Activity,在启动Activity之前,AMS需要告诉Launcher“我要启动了,你可以暂停了“,时序图如下:

    image.png

    中间通过ApplicationThreadProxy向APP端的ApplicationThread发送消息,ApplicationThread接受到AMS的消息后,调用ActivityThread的sendMessage方法,向Launcher的主线程消息队列发送一个PAUSE_ACTIVITY消息。

    @Override
    public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
                                    int configChanges, PendingTransactionActions pendingActions, String reason) {
        //获取Launcher的Activity
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            if (userLeaving) {
                performUserLeavingActivity(r);
            }
    
            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(r, finished, reason, pendingActions);
    
            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }
            mSomeActivitiesChanged = true;
        }
    }
    

    handlePauseActivity方法中从mActivities集合中,获取Launcher的Activity并让他休眠。

    到这里Launcher与AMS之间的通信就结束了,接下来的事情就是启动APP中的Activity,因为是首次启动,APP的进程不存在,需要创建一个新的进程,需要调用Process.start方法,并且指定了ActivityThread的main函数为入口函数:

    int pid=Process.start("android.app.ActivityThread",
            mSimpleProcessManagement ? app.processName:gid,
            debugFlags,
            null);
    

    为新进程创建ActivityThread对象,也就是UI线程,同时执行入口函数main,其中创建一个主线程Looper,也就是MainLooper。

    另外创建Application,主线程序会收到BIND_APPLICATION消息:

    public void handleMessage(Message msg) {
        ...
        switch (msg.what) {
            case BIND_APPLICATION:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                AppBindData data = (AppBindData)msg.obj;
                handleBindApplication(data);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
                ...
        }
        ...
    }
    

    根据传递过来的ApplicationInfo创建一个对应的LoadedApk对象,然后创建ContextImpl对象,接着通过反射创建目标Application,并调用attach方法,将ContextImpl对象设置为目标Application的上下文环境,最后调用Application的onCreate函数。

    创建完APP后,APP端通知AMS创建完毕同时把ActivityThread对象发送给AMS,同时AMS端把ActivityThread对象转换成一个ActivityThreadProxy对象,之后AMS可以向APP端发送消息,通过ActivityThreadProxy这个代理对象。

    public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }
    

    ActivityThread接受到AMS的消息,在H中发送LAUNCH_ACTIVITY消息,调用handleLaunchActivity方法,在该方法中通过Instrumentation的newActivity方法,创建要启动的Activity实例,为这个Activity创建一个上下文Context对象,并与Activity关联,通过Instrumentation的callActivityOnCreate方法,执行Activity的onCreate方法,从而启动Activity,至此APP启动完毕。

    版权声明:本文为CSDN博主「IT界的吉祥物」的原创文章
    原文链接:https://blog.csdn.net/hai_qing_xu_kong/article/details/83149367

    相关文章

      网友评论

          本文标题:app启动流程

          本文链接:https://www.haomeiwen.com/subject/asgssltx.html