1. 程式人生 > 其它 >Android外掛化架構 - Activity的啟動流程分析

Android外掛化架構 - Activity的啟動流程分析

1. 概述

Android外掛化架構,目前第三方的框架比較多,早幾年自己用的是DL框架,這個框架的原始碼比較簡單主要用的是靜態代理。如果我們自己要去寫一個外掛化架構框架那要解決的問題會分為幾個方面,類的載入,資源和佈局的載入,廣播的管理方式,Activity的載入和生命週期管理,Service的外掛化,ContentProvider的外掛化等等等等,反正載入一個沒有執行的app到主程式,需要解決的問題基本就這麼多,如果能夠一一解決那麼就可以實現外掛化了。
  內涵段子專案部分我們實現幾個,然後介紹一個360開源框架DroidPlugin原理一致,後面我們再一一實現,那麼這一期實現什麼呢?我們需要啟動外掛APP那麼就需要啟動裡面的Activity,這些Activity事先是不會在主工程的AndroidManifest.xml中配置,啟動一個沒有註冊的Activity肯定會報錯,我們是否可以想個辦法去繞過系統的檢測,讓沒有在AndroidManifest.xml中配置的Activity照樣可以啟動呢?
  看原始碼的時候我們其實時常強調一定要帶著思想,要解決這麼個問題我們肯定需要清楚的知道系統啟動Activity的具體流程,當然可以直接去了解為什麼報錯,這裡我們還是把啟動流程全部走一遍,也方便以後開發中再遇到什麼問題。

2. Activity啟動流程原始碼分析

@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);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            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 {
        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方法

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        Uri referrer = target != null ? target.onProvideReferrer() : null;
        if (referrer != null) {
            intent.putExtra(Intent.EXTRA_REFERRER, referrer);
        }
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i<N; i++) {
                    final ActivityMonitor am = mActivityMonitors.get(i);
                    if (am.match(who, null, intent)) {
                        am.mHits++;
                        if (am.isBlocking()) {
                            return requestCode >= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
    
    // 檢測結果也就是否正常
    public static void checkStartActivityResult(int res, Object intent) {
        if (res >= ActivityManager.START_SUCCESS) {
            return;
        }

        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                // 在這裡就會報各種錯,AndroidManifest.xml中沒有配置的錯就出現在這
                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);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException(
                        "FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException(
                        "PendingIntent is not an activity");
            case ActivityManager.START_NOT_VOICE_COMPATIBLE:
                throw new SecurityException(
                        "Starting under voice control not allowed for: " + intent);
            case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
                throw new IllegalStateException(
                        "Session calling startVoiceActivity does not match active session");
            case ActivityManager.START_VOICE_HIDDEN_SESSION:
                throw new IllegalStateException(
                        "Cannot start voice activity on a hidden session");
            case ActivityManager.START_CANCELED:
                throw new AndroidRuntimeException("Activity could not be started for "
                        + intent);
            default:
                throw new AndroidRuntimeException("Unknown error code "
                        + res + " when starting " + intent);
        }
    }

ActivityManagerNative.getDefault().startActivity又是一個程序間的通訊,如果不瞭解IPC的請移步 Android程序間的通訊 - IPC(機制)Binder的原理和原始碼閱讀,來到ActivityManagerService中的startActivity方法:

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null);
    }

    final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
            Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
            
            // PackageManagerService-----> 掃描app,註冊元件

            ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
            // Collect information about the target of the Intent.
            ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

            rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);

            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);
     }

     final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask) {
            
            // 驗證intent、Class、Permission等
            // 儲存將要啟動的Activity的Record
            err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                    true, options, inTask);
            return err;
      }

      private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
            // 檢查將要啟動的Activity的launchMode和啟動Flag
            // 根據launcheMode和Flag配置task
            final boolean dontStart = top != null && mStartActivity.resultTo == null
                && top.realActivity.equals(mStartActivity.realActivity)
                && top.userId == mStartActivity.userId
                && top.app != null && top.app.thread != null
                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || mLaunchSingleTop || mLaunchSingleTask);
            // 舉一個例子 SingleTop
            if (dontStart) {
                top.deliverNewIntentLocked(
                    mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);

               // Don't use mStartActivity.task to show the toast. We're not starting a new activity
               // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
               mSupervisor.handleNonResizableTaskIfNeeded(
                    top.task, preferredLaunchStackId, topStack.mStackId);
           
               return START_DELIVERED_TO_TOP;
            }

            mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
            if (mDoResume) {
                  mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
      }

進入ActvityStack中的startActivityLocked()方法

      // 任務棧歷史棧配置
      final void startActivityLocked(ActivityRecord r, boolean newTask, boolean keepCurTransition,
            ActivityOptions options) {
            if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
                // 加入棧頂 管理棧
                insertTaskAtTop(rTask, r);
                // 管顯示
                mWindowManager.moveTaskToTop(taskId);
            }
          
            if (!newTask) {
                // 不是一個新的Task
                task.addActivityToTop(r);
                r.putInHistory();
                addConfigOverride(r, task);
            }
      }

進入ActivityStack的resumeTopActivityInnerLocked()方法

      private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
           // Find the first activity that is not finishing.
           final ActivityRecord next = topRunningActivityLocked();
            
           // The activity may be waiting for stop, but that is no longer
           // appropriate for it.
           mStackSupervisor.mStoppingActivities.remove(next);
           mStackSupervisor.mGoingToSleepActivities.remove(next);
           next.sleeping = false;
           mStackSupervisor.mWaitingVisibleActivities.remove(next);

          if (mResumedActivity != null) {
              if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
              pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
          }
      }

      final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean dontWait) {
            
            if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                // 暫停Activity
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            }

            completePauseLocked(false, resuming);
      }

進入ApplicationThread的schedulePauseActivity()方法

      public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
         
                sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                    configChanges,
                    seq);
      }

      public void handleMessage(Message msg) {
            switch (msg.what) {
                ...
            case PAUSE_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handlePauseActivity((IBinder) args.arg1, false,
                            (args.argi1 & USER_LEAVING) != 0, args.argi2,
                            (args.argi1 & DONT_REPORT) != 0, args.argi3);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
           } break;
       }

       private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
            //... 
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
            //...
            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
       }

       final Bundle performPauseActivity(IBinder token, boolean finished,
            boolean saveState, String reason) {
            ActivityClientRecord r = mActivities.get(token);
            return r != null ? performPauseActivity(r, finished, saveState, reason) : null;
       }

       final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState, String reason) {
            // ...
            performPauseActivityIfNeeded(r, reason);
       }

       private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
            // ...
            mInstrumentation.callActivityOnPause(r.activity);
       }

進入Instrumentation的callActivityOnPause()方法

    public void callActivityOnPause(Activity activity) {
        activity.performPause();
    }

進入Activity的performPause()方法

final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        // 呼叫onPause()暫停方法
        onPause();
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        mResumed = false;
    }

總算是回撥到了Activity的onPause方法,哈哈還是挺簡單的,Activity生命週期中的onPause方法終於被我們找到了。也就是說我們在啟動一個Activity的時候最先被執行的是棧頂的Activity的onPause方法。我們對Activity這些生命週期早已背得滾瓜爛熟。接著往下看然後回到我們ApplicationThread的handlePauseActivity()方法中的ActivityManagerNative.getDefault().activityPaused(token);進入ActivityManagerService中的activityPaused()方法

     @Override
     public final void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized(this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                stack.activityPausedLocked(token, false);
            }
        }
        Binder.restoreCallingIdentity(origId);
     }

進入ActivityStack中的activityPausedLocked()方法

    final void activityPausedLocked(IBinder token, boolean timeout){
        completePauseLocked(true, null);
    }
    private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
        ActivityRecord prev = mPausingActivity;
        if (resumeNext) {
            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
            mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
        }
    }

進入ActivityStackSupervisor中的resumeFocusedStackTopActivityLocked()方法

    boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }

進入ActivityStack中的resumeTopActivityUncheckedLocked()方法

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        result = resumeTopActivityInnerLocked(prev, options);
    }

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        // 這個方法我們已經很熟悉了
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }

進入ActivityStackSupervisor中的startSpecificActivityLocked()方法

    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);
                }
                // 真的要啟動Activity了
                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);
    }

    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
            // scheduleLaunchActivity 啟動
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                    new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
    }

進入ApplicationThread中的scheduleLaunchActivity()方法

   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) {
            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;

            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;

            r.startsNotResumed = notResumed;
            r.isForward = isForward;

            r.profilerInfo = profilerInfo;

            r.overrideConfig = overrideConfig;
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
   }


   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;

                    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);

        // Initialize before creating the activity
        WindowManagerGlobal.initialize();

        Activity a = performLaunchActivity(r, customIntent);

        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);

                // We need to keep around the original state, in case we need to be created again.
                // But we only do this for pre-Honeycomb apps, which always save their state when
                // pausing, so we can not have them save their state when restarting from a paused
                // state. For HC and later, we want to (and can) let the state be saved as the
                // normal part of stopping the activity.
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
        } else {
            // 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();
            }
        }
    }

3. Activity啟動流程總結

剛開始去看估計要看個一兩天才會有所收貨,其實看原始碼要麼是為了解決問題要麼是為了學習,否則還是不要輕易的進入這趟渾水裡面,程式碼太多了沒有思想會蒙的。首先可以大致先走一遍流程,然後再去抓細節,比如怎麼分配棧的,怎麼處理啟動模式的,怎麼建立Activity的,怎麼呼叫生命週期的,怎麼傳遞序列化物件引數的等等…
  看了原始碼之後我們不得不佩服Google的工程師,寫的程式碼可擴充套件真的很不錯,要是換做一般人版本迭代幾次程式碼就改不動了,得要重新架構重新寫,這也是我們學習的方式,原始碼其實是最好的書籍。這裡有好幾個思想,C/S架構思想就是服務思想,模組化思想,分層次思想等等…

最後我們看一下在啟動流程中出現的幾個主要的類都分別有什麼功能:

** ActivityManagerService** 元件通訊系統核心管理類 (ActivityManagerNative)IPC通訊
** ActivityStackSupervisor** 管理整個手機的Activity任務棧
ActivityStack Activity棧(任務棧)
** PackageManagerService** 主要負責對系統的apk進行管理,不管是系統apk(/system/app),還是我們手工安裝上去的,系統所有的apk都是由其管理的。
** ActivityThread** Activity的入口是onCreate方法,Android上一個應用的入口是ActivityThread。和普通的Java類一樣有一個main方法。用於控制與管理一個應用程序的主執行緒的操作,包括管理與處理activity manager傳送過來的關於activities、廣播以及其他的操作請求
ActivityManagerService和ActivityStack位於同一個程序中,而ApplicationThread和ActivityThread位於另一個程序中。其中,ActivityManagerService是負責管理Activity的生命週期的,ActivityManagerService還藉助ActivityStack是來把所有的Activity按照後進先出的順序放在一個堆疊中;對於每一個應用程式來說,都有一個ActivityThread來表示應用程式的主程序,而每一個ActivityThread都包含有一個ApplicationThread例項,它是一個Binder物件,負責和其它程序進行通訊。

這麼痛苦的去讀原始碼到底有什麼用呢?那麼結合動態程式碼設計模式以及Activity的啟動流程,我們就可以嘗試去攔截Activity的啟動流程,讓沒有在AndroidMainfest.xml中註冊的Activity也能啟動並且不報錯,這樣我們就算是跨出了外掛化架構的第一步了,如果你不去了解Activity啟動流程那麼就是然並卵。

相關視訊
一次讓你徹底掌握Android外掛化,征服面試!