Android 插件化分析(3)- Activity启动流程

在真正分析插件化技术前,我们必须了解一些必要的关于Android四大组件的相关知识。

以Activity为例,我们需要了解Activity启动过程,才能有效的进行Hook实现插件化。

以Android 8.1为例

我们启动一个Activity通常会使用startActivity方法,但是在Activity内部最终都会调用startActivityForResult方法

    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);
            ......
        } else {
            ......
        }
    }

在这个方法的内部实际是调用Instrumentation类的execStartActivity方法。

在这里我们遇到了三个非常重要的类。

  1. Instrumentation : 随着Activity内部会持有一个对Instrumentation的引用,
  2. ActivityThread : 主线程,在app启动的时候创建的,代表了Android应用程序,里面包含了Main函数
  3. ApplicationThread : App端在system进程的代理类(涉及到Binder机制)

接着会调用Instrumentation内部的execStartAcivitiesAsUser方法

    public void execStartActivitiesAsUser(Context who, IBinder contextThread,
            IBinder token, Activity target, Intent[] intents, Bundle options,
            int userId) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ......
        try {
            .......
            int result = ActivityManager.getService()
                .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
                        token, options, userId);
            checkStartActivityResult(result, intents[0]);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
    }

然后我们进入ActivityManager内部,getService实际返回的是一个单例对象,持有AMS在app端的远程代理对象。

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

所以从这里就从app进程进入到system进程。

AMS里的代码很多,逻辑非常复杂,只要知道AMS会对传递过来的Intent进行检查,如果需要启动的Activity没有在manifest里申明,就会把错误码返回给Instrumentation,从而Instrumentation就会抛出经典的ActivityNofFoundException异常。

如果通过AMS的检查,那么会回调ApplicationThread的scheduleLauncherActivity方法

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

            ......

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

给H发送了一个LAUNCH_ACTIVITY的消息

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


就正式开始了Activity的启动过程。

从以上的分析,我们是无法启动一个没有manifest注册的Activity,但是插件化技术却可以绕过AMS的检查达到这样一个目的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值