Android Small插件化框架--启动插件Activity源码解析(下)

2023-11-07

转自:http://m.blog.csdn.net/article/details?id=53158432

参考博文

http://www.tuicool.com/articles/EjEJNrJ
http://m.w2bc.com/article/126583

AMS对startActivity请求处理及返回过程

根据上一章的分析了解了调用startActivity(),终于把数据和要开启Activity的请求发送到了AMS了,接下来分析在AMS中的处理过程和重新回到app进程。

1、在AMS中处理的过程

AMS中处理startActivity的过程比较复杂,主要涉及了ActivityManagerService、ActivityStackSupervisor、ActivityStack、PackageManagerService、WindowManagerService等几个类。

在ActivityManagerService中,startActivity先是调用了startActivityAsUser(注意,第一个参数caller就是app在服务端的代理ApplicationThreadProxy,它是一个Binder对象,实现了IApplicationThread。):

    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());
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

然后在startActivityAsUser中调用了ActivityStackSupervisor的startActivityMayWait。

    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) {
        ......
        // 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);
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

转到ActivityStackSupervisor中后,又在它和ActivityStack之间来回调用了许多次,主要是进行栈和Task的管理、解析Activity的信息,准备窗口的切换之类的工作,最后回到了ActivityStackSupervisor中,调用realStartActivityLocked函数。

    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
            ......
            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);
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在realStartActivityLocked函数中,app是ProcessRecord类型,app.thread是IApplicationThread类型,也就是从客户端的代理ApplicationThreadProxy,在这儿调用了它的scheduleLaunchActivity方法,接下来就是回到app的进程空间里的过程。

2、AMS回到app进程

再回顾一下AMS和app之间交互原理图:

ActivityThread的类图结构:

ApplicationThreadProxy中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) throws RemoteException {
        ......
        mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,
                IBinder.FLAG_ONEWAY);
        data.recycle();
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在该方法中调用IBinder的transact发出命令,然后由ApplicationThread的代理ApplicationThreadNative的onTransact来处理:

    @Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
            ......
            case SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION:
        {
            ......
            scheduleLaunchActivity(intent, b, ident, info, curConfig, overrideConfig, compatInfo,
                    referrer, voiceInteractor, procState, state, persistentState, ri, pi,
                    notResumed, isForward, profilerInfo);
            return true;
        }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

ApplicationThreadNative的onTransact函数会调用scheduleLaunchActivity,其具体实现在ApplicationThread中:

    private class ApplicationThread extends ApplicationThreadNative {
        ......
        @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) {

            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);
        }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

ApplicationThread是ActivityThread里的一个内部类,它的scheduleLaunchActivity的实现就是发一个LAUNCH_ACTIVITY类型的message到ActivityThread中的一个handler上。

    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;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
        ......
        }
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

H类继承自Handler也是Activity Thread的内部类,重写了handleMessage(Message msg)方法。根据标识LAUNCH_ACTIVITY调用了handleLaunchActivity()方法,handleLaunchActivity里调用了performLaunchActivity:

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        ......  
        Activity a = performLaunchActivity(r, customIntent);
    }

  
  
  • 1
  • 2
  • 3
  • 4
  • 5

performLaunchActivity中又用到了Instrumentation类,调它的newActivity函数构造出activity对象。newActivity函数很简单,直接用classLoader加载了Activity类,然后用反射调它的构造函数newInstance出activity实例:

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
        public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

然后再回到performLaunchActivity中,在通过newActivity得到activity的实例后,接下来就该调用它的生命周期函数onCreate了,照旧还是通过Instrumentation来完成,调用它的callActivityOnCreate函数。

                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在callActivityOnCreate里会调用Activity的performCreate函数,它里面调用的就是我们熟悉的onCreate了。

    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        restoreHasCurrentPermissionRequest(icicle);
        onCreate(icicle, persistentState);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

app到AMS过程时序图:

 
总结:到此为止,startActivity的整个流程就结束了,从整个完整流程可以看出,Instrumentation这个类是startActivity整个过程中的必经之路,无论是从app到AMS,还是从AMS回到app都会经过它,所以它就是Hook对象。并且它是ActivityThread里的一个成员mInstrumentation,所以我们在客户端进程中可以通过反射拿到ActivityThread对象,也可以拿到mInstrumentation。

在早期版本中,作者hook的是newActivity,最新版本将其改为对handler.callback进行hook。为什么?

通过请教作者,他给我的答复是:“提前hook时机,可以减少“善后”工作,handler是跑到App进程最开始的地方,到了newActivity实际上有很多事已经被做掉了,需要再通过反射来重置一些参数,比如Resources,这意味着一件事你实际上做了两次。所以越早处理越好。”

Small中对StartActivity的返回处理解析

根据以上原理分析我们知道ActivityThread中的内部类H继承自handler处理主线程消息对列(MessageQueue)中的Message。因为Android的UI操作是由handler机制进行的,所以在Activity的创建需要通过H类处理。Small框架在对AMS到app的过程进行Hook的就是H类。具体在ApkBundleLauncher实现如下:

     public void setUp(Context context) {
        ......
        // 反射获取ActivityThread类中mH成员变量
        field = activityThreadClass.getDeclaredField("mH");
        field.setAccessible(true);
        //获得activityThread对象中mH成员变量的属性值
        Handler ah = (Handler) field.get(thread);

        //反射获取Handler类中mCallback成员变量
        field = Handler.class.getDeclaredField("mCallback");
        field.setAccessible(true);
        //向ah对象中赋值为ActivityThreadHandlerCallback()
        //此刻的field是mCallback成员变量,下面就将ActivityThreadHandlerCallback的实例赋给mCallback变量
        field.set(ah, new ActivityThreadHandlerCallback());

    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

由以上可知Small主要改变了H类中mCallback成员变量的值。
为什么要这样做呢?
根据handler源码解析可知,Handler内部是通过执行dispatchMessage方法以实现对Message的处理的,Handler的dispatchMessage的源码如下:

    public void dispatchMessage(Message msg) {
        //注意下面这行代码
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
             //注意下面这行代码
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
             //注意下面这行代码
            handleMessage(msg);
        }
}
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

我们来分析下这段代码:
1.首先会判断msg.callback存不存在,如果msg.callback存在,这种情况下会执行handleCallback(msg), handleCallback源码如下:

private static void handleCallback(Message message) {
        message.callback.run();
}
  
  
  • 1
  • 2
  • 3

2.如果msg.callback就是null,代码继续往下执行,接着我们会判断Handler的成员字段mCallback存不存在。mCallback是Hanlder.Callback类型的,我们在上面提到过,在Handler的构造函数中我们可以传递Hanlder.Callback类型的对象,该对象需要实现handleMessage方法,如果我们在构造函数中传递了该Callback对象,那么我们就会让Callback的handleMessage方法来处理Message。

3.如果我们在构造函数中没有传入Callback类型的对象,那么mCallback就为null,那么我们会调用Handler自身的hanldeMessage方法,该方法默认是个空方法,我们需要自己是重写实现该方法。

综上,我们可以看到Handler提供了三种途径处理Message,而且处理有前后优先级之分:首先尝试让postXXX中传递的Runnable执行,其次尝试让Handler构造函数中传入的Callback的handleMessage方法处理,最后才是让Handler自身的handleMessage方法处理Message。

因此Small对mCallback进行hook实现的就是第二种处理方式,ActivityThreadHandlerCallback中具体代码如下:

    private static class ActivityThreadHandlerCallback implements Handler.Callback {

        private static final int LAUNCH_ACTIVITY = 100;

        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what != LAUNCH_ACTIVITY) return false;

            Object/*ActivityClientRecord*/ r = msg.obj;
            //获取到r中的Intent对象
            Intent intent = ReflectAccelerator.getIntent(r);
            //使用unwrapIntent方法将插件的类名赋给targetClass
            String targetClass = unwrapIntent(intent);
            if (targetClass == null) return false;

            // 替换上插件类对应的activityInfo
            ActivityInfo targetInfo = sLoadedActivities.get(targetClass);
            ReflectAccelerator.setActivityInfo(r, targetInfo);
            return false;
        }
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

代码分析可知,handleMessage方法中主要
是将msg.obj中存根的activityInfo中变成插件类对应的activityInfo,以供后续实例Activity和调用onCreate时使用。

重点:
重写的mCallback.handleMessage(msg)返回的是false,为什么要这样做呢?
这样做的目的是为了实现在handler里dispatchMessage方法中对Message的处理除了执行了第二种方式,还接着执行第三种方式。这样做为了实现对源码的轻度hook来达到将存根Activity替换为插件Activity的过程。

unwrapIntent()方法解析:

    private static String unwrapIntent(Intent intent) {
        //得到该intent对象中的所有category
        Set<String> categories = intent.getCategories();
        if (categories == null) return null;

        //通过查找categories其中名为REDIRECT_FLAG的category来找到原来插件activity类名
        Iterator<String> it = categories.iterator();
        while (it.hasNext()) {
            String category = it.next();
            if (category.charAt(0) == REDIRECT_FLAG) {
                //返回对应插件activity类名
                return category.substring(1);
            }
        }
        return null;
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

app的生命周期调用最后都是由Instrumentation来执行,所以Small框架中定义的InstrumentationWrapper也对其中的callActivityOnCreate,callActivityOnStop,callActivityOnDestroy等方法进行了重写,具体如下:

callActivityOnCreate()方法解析:

        @Override
        /**为插件准备资源*/
        public void callActivityOnCreate(Activity activity, android.os.Bundle icicle) {
            do {
                if (sLoadedActivities == null) break;
                ActivityInfo ai = sLoadedActivities.get(activity.getClass().getName());
                if (ai == null) break;
                //同步插件activity对应的窗口信息
                applyActivityInfo(activity, ai);
            } while (false);
            //调用原Instrumentation的callActivityOnCreate方法
            sHostInstrumentation.callActivityOnCreate(activity, icicle);

            //如果它被其他的应用程序修改了一些,复位原先的activity instrumentation
            if (sBundleInstrumentation != null) {
                try {
                    Field f = Activity.class.getDeclaredField("mInstrumentation");
                    f.setAccessible(true);
                    Object instrumentation = f.get(activity);
                    if (instrumentation != sBundleInstrumentation) {
                        f.set(activity, sBundleInstrumentation);
                    }
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

applyActivityInfo()方法解析:

    /**
     * 申请的插件Activity信息是与插件的AndroidManifest.xml里面一样
     * @param activity
     * @param ai
     */
    private static void applyActivityInfo(Activity activity, ActivityInfo ai) {
        // Apply window attributes
        Window window = activity.getWindow();
        window.setSoftInputMode(ai.softInputMode);
        activity.setRequestedOrientation(ai.screenOrientation);
    }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

callActivityOnStop方法解析:

        @Override
        public void callActivityOnStop(Activity activity) {
            sHostInstrumentation.callActivityOnStop(activity);

            if (!Small.isUpgrading()) return;

            // If is upgrading, we are going to kill self while application turn into background,
            // and while we are back to foreground, all the things(code & layout) will be reload.
            // Don't worry about the data missing in current activity, you can do all the backups
            // with your activity's `onSaveInstanceState' and `onRestoreInstanceState'.

            // Get all the processes of device (1)
            ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
            List<RunningAppProcessInfo> processes = am.getRunningAppProcesses();
            if (processes == null) return;

            // Gather all the processes of current application (2)
            // Above 5.1.1, this may be equals to (1), on the safe side, we also
            // filter the processes with current package name.
            String pkg = activity.getApplicationContext().getPackageName();
            final List<RunningAppProcessInfo> currentAppProcesses = new ArrayList<>(processes.size());
            for (RunningAppProcessInfo p : processes) {
                if (p.pkgList == null) continue;

                boolean match = false;
                int N = p.pkgList.length;
                for (int i = 0; i < N; i++) {
                    if (p.pkgList[i].equals(pkg)) {
                        match = true;
                        break;
                    }
                }
                if (!match) continue;

                currentAppProcesses.add(p);
            }
            if (currentAppProcesses.isEmpty()) return;

            // The top process of current application processes.
            RunningAppProcessInfo currentProcess = currentAppProcesses.get(0);
            if (currentProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) return;

            // Seems should delay some time to ensure the activity can be successfully
            // restarted after the application restart.
            // FIXME: remove following thread if you find the better place to `killProcess'

            new Thread() {
                @Override
                public void run() {
                    try {
                        sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    for (RunningAppProcessInfo p : currentAppProcesses) {
                        android.os.Process.killProcess(p.pid);
                    }
                }
            }.start();
        }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

callActivityOnDestroy()方法解析:

        @Override
        public void callActivityOnDestroy(Activity activity) {
            do {
                if (sLoadedActivities == null) break;
                String realClazz = activity.getClass().getName();
                ActivityInfo ai = sLoadedActivities.get(realClazz);
                if (ai == null) break;
                //存根activity与真实activity解绑
                inqueueStubActivity(ai, realClazz);
            } while (false);
            //调用原Instrumentation的callActivityOnDestroy方法
            sHostInstrumentation.callActivityOnDestroy(activity);
        }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在调用到callActivityOnDestroy时,需要将存根activity与真实activity解绑,主要通过inqueueStubActivity方法实现:

        private void inqueueStubActivity(ActivityInfo ai, String realActivityClazz) {
            if (ai.launchMode == ActivityInfo.LAUNCH_MULTIPLE) return;
            if (mStubQueue == null) return;
            int countForMode = STUB_ACTIVITIES_COUNT;
            int offset = (ai.launchMode - 1) * countForMode;
            for (int i = 0; i < countForMode; i++) {
                String stubClazz = mStubQueue[i + offset];
                if (stubClazz != null && stubClazz.equals(realActivityClazz)) {
                    mStubQueue[i + offset] = null;
                    break;
                }
            }
        }
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

从ActivityInfo获取launchMode,通过启动模式和插件Activity类名找到对存根Activity对应的mStubQueue数组位置并将其赋值为null,这样就实现了解绑。
**
关键问题:**
参考博客
1、由于我们欺骗了 AMS , AMS 应该只知道 StubActivity 的存在,它压根儿就不知道TargetActivity是什么,为什么它能正确完成对TargetActivity生命周期的回调呢?

一切的秘密在 token 里面。 AMS 与 ActivityThread 之间对于Activity的生命周期的交互,并没有直接使用Activity对象进行交互,而是使用一个token来标识,这个token是binder对象,因此可以方便地跨进程传递。Activity里面有一个成员变量 mToken 代表的就是它,token可以唯一地标识一个Activity对象,它在Activity的 attach 方法里面初始化;
在 AMS 处理Activity的任务栈的时候,使用这个token标记Activity,因此在Small里面, AMS 进程里面的token对应的是StubActivity,也就是 AMS 还在傻乎乎地操作StubActivity(关于这一点,你可以dump出任务栈的信息,可以观察到dump出的确实是StubActivity)。但是在我们App进程里面,token对应的却是TargetActivity!因此,在ActivityThread执行回调的时候,能正确地回调到TargetActivity相应的方法。

2、为什么App进程里面,token对应的是TargetActivity呢?
回到代码,ActivityClientRecord是在 mActivities 里面取出来的,确实是根据token取;那么这个token是什么时候添加进去的呢?我们看performLaunchActivity就完成明白了:它通过classloader加载了TargetActivity,然后完成一切操作之后把这个activity添加进了 mActivities !另外,在这个方法里面我们还能看到对Ativity attact 方法的调用,它传递给了新创建的Activity一个token对象,而这个token是在ActivityClientRecord构造函数里面初始化的。
至此我们已经可以确认,通过这种方式启动的Activity有它自己完整而独立的生命周期!

最后总结:至此,我们对Small框架中解决“Activity注册和生命周期问题”,从原理和代码两方面做了一个全面的分析。这个过程中,我弄懂了Android的activity启动流程,领会了Small框架怎么通过轻度hook实现对Android插件化的。写了这两篇博文,希望对你有帮助。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android Small插件化框架--启动插件Activity源码解析(下) 的相关文章

随机推荐