- 概述
Android插件化架构,目前第三方的框架比拟多,早几年本人用的是DL框架,这个框架的源码比较简单次要用的是动态代理。如果咱们本人要去写一个插件化架构框架那要解决的问题会分为几个方面,类的加载,资源和布局的加载,播送的治理形式,Activity的加载和生命周期治理,Service的插件化,ContentProvider的插件化等等等等,反正加载一个没有运行的app到主程序,须要解决的问题根本就这么多,如果可能一一解决那么就能够实现插件化了。
外延段子我的项目局部咱们实现几个,而后介绍一个360开源框架DroidPlugin原理统一,前面咱们再一一实现,那么这一期实现什么呢?咱们须要启动插件APP那么就须要启动外面的Activity,这些Activity当时是不会在主工程的AndroidManifest.xml中配置,启动一个没有注册的Activity必定会报错,咱们是否能够想个办法去绕过零碎的检测,让没有在AndroidManifest.xml中配置的Activity照样能够启动呢?
看源码的时候咱们其实时常强调肯定要带着思维,要解决这么个问题咱们必定须要分明的晓得系统启动Activity的具体流程,当然能够间接去理解为什么报错,这里咱们还是把启动流程全副走一遍,也不便当前开发中再遇到什么问题。 - Activity启动流程源码剖析
@Overridepublic 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(); } } }
- 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插件化,驯服面试!