Activity的启动过程分析

Activity的启动过程

首先先列出Activity启动的过程中调用的一些方法,因为activity启动涉及到各种方法调用,而且调用的路线也各不一样,这里只会对activity启动的一条线进行分析,有兴趣的同学可以读android的源码进行分析

  1. Activity
    • startActivity
    • startActivityForResult
  2. Instrumentation
    • execStartActivity
  3. ActivityManagerProxy
    • startActivity
  4. ActivityManagerService
    • startActivity
    • startActivityAsUser
  5. ActivityStarter
    • startActivityMayWait
    • startActivityLocked
    • startActivityUnchecked
    • postStartActivityUncheckedProcessing
  6. ActivityStack
    • startActivityLocked
  7. ActivityStackSupervisor
    • resumeFocusedStackTopActivityLocked
  8. ActivityStack
    • resumeTopActivityUncheckedLocked
    • resumeTopActivityInnerLocked
  9. ActivityThread
    • scheduleLaunchActivity
    • H(Handler) - LAUNCH_ACTIVITY

通过源码发现,startActivity进入到startActivityForResult的方法,然后进入到Instrumentation的execStartActivity方法。

在进入Instrumentation之前,先对Instrumentation做简短的介绍:

  1. 其包含有2个内部类:ActivityMoniter、ActivityResult

    ActivityMoniter:有关特定的Intent的监视。一个ActivityMoniter类的实例通过函数addMonitor(Instrumentation.ActivityMonitor)添加到当前instrumentation中,一旦添加后,每当启动一个新的Activity,ActivityMoniter就会检测,如果匹配,其hit count计数更新等其他操作。 一个ActivityMonitor也可以用来寻找一个Activity,通过waitForActivity()方法,这个函数将返直到匹配的活动被创建。
    ActivityResult:一个活动执行的结果说明,返回到原来的活动。

  2. 创建,暂停和恢复Activity的时候,都是通过调用Instrumentation的callActivityOnCreate,callActivityOnPause和callActivityOnResume等方法来实现对Activity方法生命周期调用


    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) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            // 跳出Activity方法,进入到execStartActivity方法
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                // 通知Activity启动的结果,这里会调用栈顶的Activity调用onPause方法
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            // 这里是低版本的系统启动Activity的方式,这里不进行分析
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

我们进入到Instrumentation的execStartActivity方法,下面对execStartActivity的参数进行解析,
从源码可以看出,Instrumentation直接进入了ActivityManagerNative的startActivity方法,随后会调用checkStartActivityResult,这个方法会检查返回结果是否中Activity是否在AndroidManifest.xml中注册,如果没有就会抛出异常等。


    public class Instrumentation {

        ...省略代码

        public ActivityResult execStartActivity(...省略参数) {
            ...省略代码
            // 进入到ActivityManagerProxy
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);

            // 检查startActivity返回结果是否成功
            checkStartActivityResult(result, intents[0]);
            ...省略代码
            return null;
        }

        public static void checkStartActivityResult(...省略参数) {
            if (res >= ActivityManager.START_SUCCESS) {
                return;
            }
    
            switch (res) {
                ...省略代码
                // 此处是没有在AndroidManifest.xml里注册Activity时报的
                case ActivityManager.START_INTENT_NOT_RESOLVED:
                case ActivityManager.START_CLASS_NOT_FOUND:
                    if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                        throw new ActivityNotFoundException(
                                "Unable to find explicit activity class "
                                + ((Intent)intent).getComponent().toShortString()
                                + "; have you declared this activity in your AndroidManifest.xml?");
                    throw new ActivityNotFoundException(
                            "No Activity found to handle " + intent);
                ...省略代码
            }
        }

        ...省略代码
    }

然后我们进入到ActivityManagerNative,下面对Activity的参数进行分析

  1. who:Activity的启动者
  2. contextThread:当前Activity的启动进程
  3. token:记录启动Activity的token值,有可能为空
  4. target:启动者,即启动新Activity的那个Activity
  5. intent:意图
  6. requestCode:启动Activity后,返回给当前Activity的值,通过onActivityResult返回
  7. options:附加参数

而ActivityMangagerNitive调用的是ActivityManagerProxy的startActivity方法,最后调用mRemote方法,mRemote是Binder类型,由此可见这里startActivity是通过调用远程ActivityManagerService的binder调用的是远程的onStransct方法,而ActivityManagerService是ActivityMangagerNitive的子类,onStransct的实现是在ActivityMangagerNitive,所以我们进入到ActivityMangagerNitive,从ActivityMangagerNitive的onTransact方法可以看出调用的是子类的startActivity方法,我们知道ActivityManagerNative的子类是ActivityManagerService。

这里涉级到一个技巧,我们每个Activity都必须到AndroidManifest.xml里面去注册否则我们就无法启动这个Activity,我们是否想到有没有可能不注册Activity就能启动这个Activity呢?答案是肯定的,我们可以在AndroidManifest.xml里面注册一个代理的Activity,只要在进入ActivityManagerNative方法后,我们把我们的启动Activity换成一个在AndroidManifest.xml中己经注册好的代理类Activity,这样就可以欺骗系统说,我己经注册了这个Activity了,你不需要抛出找不到Activity的异常。


    public abstract class ActivityManagerNative extends Binder implements IActivityManager

        // 这是远程ActivityManagerService的onTransact方法
        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
                throws RemoteException {
            switch (code) {
            // 根据传过来的code类型,我们知道会调用到进入到下面的case去
            case START_ACTIVITY_TRANSACTION:
            {
                ....省略代码
                // 调用startActivity方法,具体的实现在ActivityManagerService
                int result = startActivity(app, callingPackage, intent, resolvedType,
                        resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
                ...省略代码
                return true;
            }
        }

        class ActivityManagerProxy implements IActivityManager
    
            ...省略代码
            public int startActivity(...省略参数) throws RemoteException {
                ...
                // 调用远程的transact方法,带上START_ACTIVITY_TRANSACTION的code类型
                // 并把所有的参数都带到远程去
                mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
                ...
                return result;
            }
    
            ...省略代码
        }
    }

下面我们分析ActivityManagerService的startActivity方法,startActivity调用的是startActivityAsUsery方法,startActivity比startActivityAsUsery多出了UserId,有了这个UserId,就可以检查调用者的权限。而startActivityAsUser会跳到ActivityStarter的startActivityMayWait方法


    public final class ActivityManagerService extends ActivityManagerNative
            implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

        ...省略代码

        @Override
        public final int startActivity(...省略参数) {
            return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId());
        }

        ...省略代码


        @Override
        public final int startActivityAsUser(...省略参数) {
            ...省略代码
            // 跳出ActivityManagerSerivce,进入到ActivityStarter的startActivityMayWait方法
            return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                    profilerInfo, null, null, bOptions, false, userId, null, null);
        }

    }

下面我们进入到ActivityStarter类,因为ActivityStarter类涉及的方法太多,这里只是会分析几个重要的调用:

  1. 首先,我们进入到ActivityStarter的startActivityMayWait方法 此方法里面mSupervisor.resolveIntent(intent, resolvedType, userId)会进入到PackageManagerService的resolveIntent方法,此方法是开发者使用隐式调用时,会弹出选择窗让用户自己使择打开的应用

  2. 然后,我们进入到了ActivityStarter的startActivityLocked方法, 此方法大部份是对调用者的权限进行验证,看是否调用者是否有权限进行操作

  1. 然后进入到ActivityStarter的startActivityUnchecked方法,此方法主要是判断Activity是以什么方式启动,还有以什么方式入Activity栈, 例如computeLaunchingTaskFlags(); 判断Activity启动的以什么方式启动

  2. 然后我们进入到ActivityStack的startActivityLocked方法,这方法主要是设置Activity的准备工作己经完成

  3. 最后由postStartActivityUncheckedProcessing方法发出通知Activity的启动工作完成


    class ActivityStarter {
        
        final int startActivityMayWait(...省略参数) {
                
                ...省略代码

                ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);

                ...省略代码

                // 进入到startActivityLocked方法,此方法主要是检查Activity启动的权限
                int res = startActivityLocked(caller, intent, ephemeralIntent,  resolvedType, aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                    inTask);
    
                ...省略代码

                return res;
            }
        }


        final int startActivityLocked(...省略参数) {

            ....省略代码
            
            // 
            if (abort) {
                if (resultRecord != null) {
                    resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
                            RESULT_CANCELED, null);
                }
                // We pretend to the caller that it was really started, but
                // they will just get a cancel result.
                ActivityOptions.abort(options);
                return START_SUCCESS;
            }
    
            try {
                err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true, options, inTask);
            } finally {
                mService.mWindowManager.continueSurfaceLayout();
            }
            postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord,     mTargetStack);
            return err;
        }


        private int startActivityUnchecked(final ActivityRecord r, ActivityRecord   sourceRecord,   sume, ActivityOptions options,  TaskRecord inTask) {

            setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor);
    
            // 还是用来初始化启动标志位的
            computeLaunchingTaskFlags();
    
            computeSourceStack();
    
            ...省略代码
    
            mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);

            ...省略代码

            return START_SUCCESS;
        }

        void postStartActivityUncheckedProcessing(
            ActivityRecord r, int result, int prevFocusedStackId, ActivityRecord sourceRecord,
            ActivityStack targetStack) {

            ...省略代码
        
            // We're waiting for an activity launch to finish, but that activity simply
            // brought another activity to front. Let startActivityMayWait() know about
            // this, so it waits for the new activity to become visible instead.
            if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) {
                mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
            }

            ...省略代码

        }

        ...省略代码
    }



    final class ActivityStack {
        
        ...省略代码

        final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
                ActivityOptions options) {
        
            ...省略代码

            // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
            // tell WindowManager that r is visible even though it is at the back of the stack.
            mWindowManager.setAppVisibility(r.appToken, true);

            ...

        }
        
        ...

    }

下面我们进入到ActivityStackSupervisor源码,reportTaskToFrontNoLaunch的作用是如果change为true就通知通知ActivityStarter待启动Activity对应的Task移动到了前台


    public final class ActivityStackSupervisor implements DisplayListener {

        ...省略代码

        void reportTaskToFrontNoLaunch(ActivityRecord r) {
            boolean changed = false;
            for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
                WaitResult w = mWaitingActivityLaunched.remove(i);
                if (w.who == null) {
                    changed = true;
                    // Set result to START_TASK_TO_FRONT so that startActivityMayWait() knows that
                    // the starting activity ends up moving another activity to front, and it should
                    // wait for this new activity to become visible instead.
                    // Do not modify other fields.
                    w.result = START_TASK_TO_FRONT;
                }
            }
            if (changed) {
                //notifyAll通知ActivityStarter待启动Activity对应的Task移动到了前台
                mService.notifyAll();
            }
        }

        ...省略代码

    }

发送通知后,就会调用ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法,然后调ActivityStack的resumeTopActivityUncheckedLocked方法,再调用ActivityStack的resumeTopActivityInnerLocked,最后进入到ActivityThread的scheduleLaunchActivity方法

前面讲过可以启动一个没有在AndroidManifest.xml里面注册过的Activity,只需要用动态代理的方法,把H的handleMessage拦截,然后在这里把我们没有注册的Activity放回到intent里面就可以实现启动没有注册的Activity



    public final class ActivityThread {

        public static void main(String[] args) {
            ...省略代码
    
            // 下面是启动UI主线程
            Looper.prepareMainLooper();
    
            ActivityThread thread = new ActivityThread();
            thread.attach(false);
    
            if (sMainThreadHandler == null) {
                sMainThreadHandler = thread.getHandler();
            }
    
            if (false) {
                Looper.myLooper().setMessageLogging(new
                        LogPrinter(Log.DEBUG, "ActivityThread"));
            }
    
            // End of event ActivityThreadMain.
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            Looper.loop();
    
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }

        @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            ...
            // 发送启动Activity的消息
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

    


        private class H extends Handler {
            ...省略代码
            public void handleMessage(Message msg) {
                if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
                switch (msg.what) {
                    case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;、

                    // 获取Activity信息
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                    ...
                }
            }
            ...省略代码
        }
        
        private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
            // If we are getting ready to gc after going to the background, well
            // we are back active so skip it.
            unscheduleGcIdler();
            mSomeActivitiesChanged = true;
    
            if (r.profilerInfo != null) {
                mProfiler.setProfiler(r.profilerInfo);
                mProfiler.startProfiling();
            }
    
            // Make sure we are running with the most recent config.
            handleConfigurationChanged(null, null);
    
            if (localLOGV) Slog.v(
                TAG, "Handling launch of " + r);
    
            // 初始化WindowManagerService服务
            WindowManagerGlobal.initialize();
    
            // 创建Activity,这里会执行Activity的生命周期
            Activity a = performLaunchActivity(r, customIntent);
    
            // 如果Activity不为空,则启动Activity
            if (a != null) {
                r.createdConfig = new Configuration(mConfiguration);
                reportSizeConfigurations(r);
                Bundle oldState = r.state;
                handleResumeActivity(r.token, false, r.isForward,
                        !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
    
                if (!r.activity.mFinished && r.startsNotResumed) {
                    // The activity manager actually wants this one to start out paused, because it
                    // needs to be visible but isn't in the foreground. We accomplish this by going
                    // through the normal startup (because activities expect to go through onResume()
                    // the first time they run, before their window is displayed), and then pausing it.
                    // However, in this case we do -not- need to do the full pause cycle (of freezing
                    // and such) because the activity manager assumes it can just retain the current
                    // state it has.
                    performPauseActivityIfNeeded(r, reason);
    
                    ...
                }
            } else {
                // 找不到需要启动的Activity报错
                // If there was an error, for any reason, tell the activity manager to stop us.
                try {
                    ActivityManagerNative.getDefault()
                        .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
        }
    }

这里只对Activity的启动流程分析,没有对每个方法进行详情的分析,有兴趣的读者可以看Android的源码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容