探究APP应用启动过程

来源:互联网 发布:恩牛网络怎么样 编辑:程序博客网 时间:2024/05/21 07:03

一:前言

相信很多Android开发人员都知道Application、Activity的生命周期是什么,但是具体的启动流程却不太清晰,我们不是盲目的写代码,理清这一点可以帮助我们更好的学习。

二:从源码分析

1.app应用程序是由Launcher启动起来的

public final class Launcher extends Activity        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, AllAppsView.Watcher {    ...    public void onClick(View v) {        Object tag = v.getTag();        if (tag instanceof ShortcutInfo) {            // Open shortcut            final Intent intent = ((ShortcutInfo) tag).intent;            int[] pos = new int[2];            v.getLocationOnScreen(pos);            intent.setSourceBounds(new Rect(pos[0], pos[1],                pos[0] + v.getWidth(), pos[1] + v.getHeight()));            startActivitySafely(intent, tag);        } else if (tag instanceof FolderInfo) {            ......        }    }    void startActivitySafely(Intent intent, Object tag) {        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);        try {            startActivity(intent);        } catch (ActivityNotFoundException e) {            ......        }     }    ......}

2.Activity.startActivityForResult(Launcher继承Activity往下执行startActivity)

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {        if (mParent == null) {            Instrumentation.ActivityResult ar =                mInstrumentation.execStartActivity(                    this, mMainThread.getApplicationThread(), mToken, this,                    intent, requestCode, options);            ...        }else{...}       }}

主要代码:
mInstrumentation.execStartActivity(this,mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options)
字段解析:
mInstrumentation:
Instrumentation类,可以将Instrumentation理解为一种没有图形界面
的,具有启动能力的,用于监控app与android系统交互的工具类

mMainThread:
ActivityThread类,主线程,attach传入。

mToken:
IBinder对象,负责和ActivityThread进行进程间通信

3.Instrumentation.execStartActivity

public ActivityResult execStartActivity(            Context who, IBinder contextThread, IBinder token, Activity target,            Intent intent, int requestCode, Bundle options) {        ...        try {            intent.migrateExtraStreamToClipData();            intent.prepareToLeaveProcess();            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) {        }        return null;    }

ActivityManagerNative.getDefault()得到的是ActivityManagerService的远程接口ActivityManagerProxy:

 static public IActivityManager getDefault() {        return gDefault.get();    } private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {        protected IActivityManager create() {            IBinder b = ServiceManager.getService("activity");              ...            IActivityManager am = asInterface(b);              ...            return am;        }static public IActivityManager asInterface(IBinder obj) {        IActivityManager in =(IActivityManager)obj.queryLocalInterface(descriptor);        if (in != null) {            return in;        }        return new ActivityManagerProxy(obj);    }

4.ActivityManagerProxy.startActivity

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,            String resolvedType, IBinder resultTo, String resultWho, int requestCode,            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {        Parcel data = Parcel.obtain();        Parcel reply = Parcel.obtain();        data.writeInterfaceToken(IActivityManager.descriptor);        data.writeStrongBinder(caller != null ? caller.asBinder() : null);        data.writeString(callingPackage);        intent.writeToParcel(data, 0);        data.writeString(resolvedType);        data.writeStrongBinder(resultTo);        data.writeString(resultWho);        data.writeInt(requestCode);        data.writeInt(startFlags);        if (profilerInfo != null) {            data.writeInt(1);            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);        } else {            data.writeInt(0);        }        if (options != null) {            data.writeInt(1);            options.writeToParcel(data, 0);        } else {            data.writeInt(0);        }        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);        reply.readException();        int result = reply.readInt();        reply.recycle();        data.recycle();        return result;    }

5. mRemote 实际通过ActivityManagerNative.getDefault进行注册的,实际就是ActivityManagerService
IBinder b = ServiceManager.getService(“activity”);
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
调用binder的transact再到ActivityManagerNative的Ontransact方法

6.实际调用proxy中的Ontransact方法

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)throws RemoteException {        switch (code) {        case START_ACTIVITY_TRANSACTION:        {        data.enforceInterface(IActivityManager.descriptor);            IBinder b = data.readStrongBinder();            IApplicationThread app = ApplicationThreadNative.asInterface(b);            Intent intent = Intent.CREATOR.createFromParcel(data);            String resolvedType = data.readString();            Uri[] grantedUriPermissions = data.createTypedArray(Uri.CREATOR);            int grantedMode = data.readInt();            IBinder resultTo = data.readStrongBinder();            String resultWho = data.readString();              int requestCode = data.readInt();            boolean onlyIfNeeded = data.readInt() != 0;            boolean debug = data.readInt() != 0;            int result = startActivity(app, intent, resolvedType,            grantedUriPermissions, grantedMode, resultTo, resultWho,            requestCode, onlyIfNeeded, debug);            reply.writeNoException();            reply.writeInt(result);            return true;        }

6 startActivity 实际调用ActivityManagerService中的startActivity方法

public final int startActivity(IApplicationThread caller,              Intent intent, String resolvedType, Uri[] grantedUriPermissions,              int grantedMode, IBinder resultTo,              String resultWho, int requestCode, boolean onlyIfNeeded,              boolean debug) {          return mMainStack.startActivityMayWait(caller, intent, resolvedType,              grantedUriPermissions, grantedMode, resultTo, resultWho,              requestCode, onlyIfNeeded, debug, null, null);      }  

7.ActivityStack.startActivityMayWait

final int startActivityMayWait(IApplicationThread caller,            Intent intent, String resolvedType, Uri[] grantedUriPermissions,            int grantedMode, IBinder resultTo,            String resultWho, int requestCode, boolean onlyIfNeeded,            boolean debug, WaitResult outResult, Configuration config) {        ......        boolean componentSpecified = intent.getComponent() != null;        // Don't modify the client's object!        intent = new Intent(intent);        // Collect information about the target of the Intent.        ActivityInfo aInfo;        try {            ResolveInfo rInfo =                AppGlobals.getPackageManager().resolveIntent(                intent, resolvedType,                PackageManager.MATCH_DEFAULT_ONLY                | ActivityManagerService.STOCK_PM_FLAGS);            aInfo = rInfo != null ? rInfo.activityInfo : null;        } catch (RemoteException e) {            ......        }        if (aInfo != null) {            // Store the found target back into the intent, because now that            // we have it we never want to do this again.  For example, if the            // user navigates back to this point in the history, we should            // always restart the exact same activity.            intent.setComponent(new ComponentName(                aInfo.applicationInfo.packageName, aInfo.name));            ......        }        synchronized (mService) {            int callingPid;            int callingUid;            if (caller == null) {                ......            } else {                callingPid = callingUid = -1;            }            mConfigWillChange = config != null                && mService.mConfiguration.diff(config) != 0;            ......            if (mMainStack && aInfo != null &&(aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {                            ......            }            int res = startActivityLocked(caller, intent, resolvedType,                grantedUriPermissions, grantedMode, aInfo,                resultTo, resultWho, requestCode, callingPid, callingUid,                onlyIfNeeded, componentSpecified);            if (mConfigWillChange && mMainStack) {                ......            }            ......            if (outResult != null) {                ......            }            return res;        }    }

8.ActivityStack.startActivityLocked

final int startActivityLocked(IApplicationThread caller,            Intent intent, String resolvedType,            Uri[] grantedUriPermissions,            int grantedMode, ActivityInfo aInfo, IBinder resultTo,                String resultWho, int requestCode,            int callingPid, int callingUid, boolean onlyIfNeeded,            boolean componentSpecified) {            int err = START_SUCCESS;        ProcessRecord callerApp = null;        if (caller != null) {            callerApp = mService.getRecordForAppLocked(caller);            if (callerApp != null) {                callingPid = callerApp.pid;                callingUid = callerApp.info.uid;            } else {                ......            }        }        ......        ActivityRecord sourceRecord = null;        ActivityRecord resultRecord = null;        if (resultTo != null) {            int index = indexOfTokenLocked(resultTo);            ......            if (index >= 0) {                sourceRecord = (ActivityRecord)mHistory.get(index);                if (requestCode >= 0 && !sourceRecord.finishing) {                    ......                }            }        }        int launchFlags = intent.getFlags();        if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0            && sourceRecord != null) {            ......        }        if (err == START_SUCCESS && intent.getComponent() == null) {            ......        }        if (err == START_SUCCESS && aInfo == null) {            ......        }        if (err != START_SUCCESS) {            ......        }        ......        ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,            intent, resolvedType, aInfo, mService.mConfiguration,            resultRecord, resultWho, requestCode, componentSpecified);        ......        return startActivityUncheckedLocked(r, sourceRecord,            grantedUriPermissions, grantedMode, onlyIfNeeded, true);    }

9.ActivityStack.startActivityUncheckedLocked

final int startActivityUncheckedLocked(ActivityRecord r,        ActivityRecord sourceRecord, Uri[] grantedUriPermissions,        int grantedMode, boolean onlyIfNeeded, boolean doResume) {        final Intent intent = r.intent;        final int callingUid = r.launchedFromUid;        int launchFlags = intent.getFlags();        // We'll invoke onUserLeaving before onPause only if the launching        // activity did not explicitly state that this is an automated launch.        mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;        ......        ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)            != 0 ? r : null;        // If the onlyIfNeeded flag is set, then we can do this if the activity        // being launched is the same as the one making the call...  or, as        // a special case, if we do not know the caller then we count the        // current top activity as the caller.        if (onlyIfNeeded) {            ......        }        if (sourceRecord == null) {            ......        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {            ......        } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {            ......        }        if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {            ......        }        boolean addingToTask = false;        if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&            (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {                // If bring to front is requested, and no result is requested, and                // we can find a task that was started with this same                // component, then instead of launching bring that one to the front.                if (r.resultTo == null) {                    // See if there is a task to bring to the front.  If this is                    // a SINGLE_INSTANCE activity, there can be one and only one                    // instance of it in the history, and it is always in its own                    // unique task, so we do a special search.                    ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE                        ? findTaskLocked(intent, r.info)                        : findActivityLocked(intent, r.info);                    if (taskTop != null) {                        ......                    }                }        }        ......        if (r.packageName != null) {            // If the activity being launched is the same as the one currently            // at the top, then we need to check if it should only be launched            // once.            ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);            if (top != null && r.resultTo == null) {                if (top.realActivity.equals(r.realActivity)) {                    ......                }            }        } else {            ......        }        boolean newTask = false;        // Should this be considered a new task?        if (r.resultTo == null && !addingToTask            && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {                // todo: should do better management of integers.                mService.mCurTask++;                if (mService.mCurTask <= 0) {                    mService.mCurTask = 1;                }                r.task = new TaskRecord(mService.mCurTask, r.info, intent,                    (r.info.flags&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0);                ......                newTask = true;                if (mMainStack) {                    mService.addRecentTaskLocked(r.task);                }        } else if (sourceRecord != null) {            ...        } else {            ...        }        ...        startActivityLocked(r, newTask, doResume);        return START_SUCCESS;    }

10.startActivityLocked

private final void startActivityLocked(ActivityRecord r, boolean newTask,              boolean doResume) {          final int NH = mHistory.size();          int addPos = -1;          if (!newTask) {              ......          }          // Place a new activity at top of stack, so it is next to interact          // with the user.          if (addPos < 0) {              addPos = NH;          }          // If we are not placing the new activity frontmost, we do not want          // to deliver the onUserLeaving callback to the actual frontmost          // activity          if (addPos < NH) {              ......          }          // Slot the activity into the history stack and proceed          mHistory.add(addPos, r);          r.inHistory = true;          r.frontOfTask = newTask;          r.task.numActivities++;          if (NH > 0) {              // We want to show the starting preview window if we are              // switching to a new task, or the next activity's process is              // not currently running.              ......          } else {              // If this is the first activity, don't do any fancy animations,              // because there is nothing for it to animate on top of.              ......          }          ......          if (doResume) {              resumeTopActivityLocked(null);          }      }  

11.Activity.resumeTopActivityLocked

final boolean resumeTopActivityLocked(ActivityRecord prev) {          // Find the first activity that is not finishing.          ActivityRecord next = topRunningActivityLocked(null);          // Remember how we'll process this pause/resume situation, and ensure          // that the state is reset however we wind up proceeding.          final boolean userLeaving = mUserLeaving;          mUserLeaving = false;          if (next == null) {              ......          }          next.delayedResume = false;          // If the top activity is the resumed one, nothing to do.          if (mResumedActivity == next && next.state == ActivityState.RESUMED) {              ......          }          // If we are sleeping, and there is no resumed activity, and the top          // activity is paused, well that is the state we want.          if ((mService.mSleeping || mService.mShuttingDown)              && mLastPausedActivity == next && next.state == ActivityState.PAUSED) {              ......          }          ......          // If we are currently pausing an activity, then don't do anything          // until that is done.          if (mPausingActivity != null) {              ......          }          ......          // We need to start pausing the current activity so the top one          // can be resumed...          if (mResumedActivity != null) {              ......              startPausingLocked(userLeaving, false);              return true;          }          ......      }  

11.ActivityStack.startPausingLocked

private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {          if (mPausingActivity != null) {              ......          }          ActivityRecord prev = mResumedActivity;          if (prev == null) {              ......          }          ......          mResumedActivity = null;          mPausingActivity = prev;          mLastPausedActivity = prev;          prev.state = ActivityState.PAUSING;          ......          if (prev.app != null && prev.app.thread != null) {              ......              try {                  ......                  prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,                      prev.configChangeFlags);                  ......              } catch (Exception e) {                  ......              }          } else {              ......          }          ......      }  

12.ApplicationThread.scheduleLaunchActivity

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,              ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,              List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {              ActivityClientRecord r = new ActivityClientRecord();              r.token = token;              r.ident = ident;              r.intent = intent;              r.activityInfo = info;              r.state = state;              r.pendingResults = pendingResults;              r.pendingIntents = pendingNewIntents;              r.startsNotResumed = notResumed;              r.isForward = isForward;              queueOrSendMessage(H.LAUNCH_ACTIVITY, r);          }  

13.ActivityThread.queueOrSendMessage

 private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {              synchronized (this) {                  ......                  Message msg = Message.obtain();                  msg.what = what;                  msg.obj = obj;                  msg.arg1 = arg1;                  msg.arg2 = arg2;                  mH.sendMessage(msg);              }          }  

14.H.handleMessage

 case LAUNCH_ACTIVITY: {          ActivityRecord r = (ActivityRecord)msg.obj;                           r.packageInfo=getPackageInfoNoCheck(r.activityInfo.applicationInfo);          handleLaunchActivity(r);                }          }

15.ActivityThread.handleLaunchActivity

private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {          ...          Activity a = performLaunchActivity(r, customIntent);          if (a != null) {              r.createdConfig = new Configuration(mConfiguration);              Bundle oldState = r.state;              handleResumeActivity(r.token, false, r.isForward);              ...         } else {              ...          }      }  

16.ActivityThread.performLaunchActivity

public final class ActivityThread {    ......    private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {        ActivityInfo aInfo = r.activityInfo;        if (r.packageInfo == null) {            r.packageInfo = getPackageInfo(aInfo.applicationInfo,                Context.CONTEXT_INCLUDE_CODE);        }        ComponentName component = r.intent.getComponent();        if (component == null) {            component = r.intent.resolveActivity(                mInitialApplication.getPackageManager());            r.intent.setComponent(component);        }        if (r.activityInfo.targetActivity != null) {            component = new ComponentName(r.activityInfo.packageName,                r.activityInfo.targetActivity);        }        Activity activity = null;        try {            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();            activity = mInstrumentation.newActivity(                cl, component.getClassName(), r.intent);            r.intent.setExtrasClassLoader(cl);            if (r.state != null) {                r.state.setClassLoader(cl);            }        } catch (Exception e) {            ......        }        try {            Application app = r.packageInfo.makeApplication(false, mInstrumentation);            ......            if (activity != null) {                ContextImpl appContext = new ContextImpl();                appContext.init(r.packageInfo, r.token, this);                appContext.setOuterContext(activity);                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());                Configuration config = new Configuration(mConfiguration);                ......                activity.attach(appContext, this, getInstrumentation(), r.token,                    r.ident, app, r.intent, r.activityInfo, title, r.parent,                    r.embeddedID, r.lastNonConfigurationInstance,                    r.lastNonConfigurationChildInstances, config);                if (customIntent != null) {                    activity.mIntent = customIntent;                }                r.lastNonConfigurationInstance = null;                r.lastNonConfigurationChildInstances = null;                activity.mStartedActivity = false;                int theme = r.activityInfo.getThemeResource();                if (theme != 0) {                    activity.setTheme(theme);                }                activity.mCalled = false;                mInstrumentation.callActivityOnCreate(activity, r.state);                ......                r.activity = activity;                r.stopped = true;                if (!r.activity.mFinished) {                    activity.performStart();                    r.stopped = false;                }                if (!r.activity.mFinished) {                    if (r.state != null) {                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);                    }                }                if (!r.activity.mFinished) {                    activity.mCalled = false;        mInstrumentation.callActivityOnPostCreate(activity, r.state);                    if (!activity.mCalled) {                        throw new SuperNotCalledException(                            "Activity " + r.intent.getComponent().toShortString() +                            " did not call through to super.onPostCreate()");                    }                }            }            r.paused = true;            mActivities.put(r.token, r);        } catch (SuperNotCalledException e) {            ......        } catch (Exception e) {            ......        }        return activity;    }    ......}

总结步骤

一:Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity

二:ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态

三:Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行

四:ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信

五:ActivityManagerService通过Binder进程间通信机制通知ActivityThread,执行Activity的启动操作

0 0
原创粉丝点击