代理Hook方式实现监控startActivity方法

记得以前有做过应用内悬浮球的程序,通过自定义BaseActivity,然后重写startActivity方法达到监控的目的,从而实现提前预知程序状态,根据程序状态进而隐藏或显示悬浮球,以达到内置悬浮球的目的。
今天使用代理模式的思想实现监控startActivity

直接上代码

@Override
    protected void attachBaseContext(Context base) {
        
        super.attachBaseContext(base);

        try {

            Field mMainThreadField = base.getClass().getDeclaredField("mMainThread");

            mMainThreadField.setAccessible(true);

            Object mMainThread = mMainThreadField.get(base);

            Field mInstrumentationField = mMainThread.getClass().getDeclaredField("mInstrumentation");

            mInstrumentationField.setAccessible(true);

            mInstrumentationField.set(mMainThread, new MyInstrumentation((Instrumentation) mInstrumentationField.get(mMainThread)));

        } catch (Exception e) {

            System.out.println(e.toString());

        }

    }

MyInstrumentation类

class MyInstrumentation extends Instrumentation {

    Instrumentation mInstrumentation;

    public MyInstrumentation(Instrumentation mInstrumentation) {

        super();

        this.mInstrumentation = mInstrumentation;

        //加下面代码保险一点

        try {

            Method method = Class.class.getDeclaredMethod("getDeclaredFields");

            Field[] declaredFields = (Field[]) method.invoke(Instrumentation.class);

            //Android9.0后禁用了hide api,所以下面方法会有问题,已使用上面代码替换
//            Field[] declaredFields = Instrumentation.class.getDeclaredFields();

            for (Field field : declaredFields) {

                field.setAccessible(true);

                field.set(this, field.get(mInstrumentation));

            }

        } catch (Exception e) {
            System.out.println(e.toString());
        }

    }

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {

        System.out.println("startActivity:" + intent.getComponent().getClassName());

        try {
            @SuppressLint("DiscouragedPrivateApi") Method execStartActivityMethod = Instrumentation.class.getDeclaredMethod(
                    "execStartActivity",
                    Context.class,
                    IBinder.class,
                    IBinder.class,
                    Activity.class,
                    Intent.class,
                    int.class,
                    Bundle.class
            );

            return (ActivityResult) execStartActivityMethod.invoke(mInstrumentation, who, contextThread, token, target, intent, requestCode, options);

        } catch (Exception e) {

            System.out.println(e.toString());

            return null;

        }
    }

    public int execStartActivitiesAsUser(
            Context who,
            IBinder contextThread,
            IBinder token,
            Activity target,
            Intent[] intents,
            Bundle options,
            int userId) {

        try {
            @SuppressLint("DiscouragedPrivateApi") Method execStartActivitiesAsUserMethod = Instrumentation.class.getDeclaredMethod(
                    "execStartActivitiesAsUser",
                    Context.class,
                    IBinder.class,
                    IBinder.class,
                    Activity.class,
                    Intent[].class,
                    Bundle.class,
                    int.class
            );

            for (Intent intent :
                    intents) {
                System.out.println("startActivties:" + intent.getComponent().getClassName());
            }

            return (int) execStartActivitiesAsUserMethod.invoke(mInstrumentation, who, contextThread, token, target, intents, options, userId);

        } catch (Exception e) {

            System.out.println(e.toString());

            return 0;

        }

    }

}

敲一遍应该是可以看懂滴

发布了77 篇原创文章 · 获赞 44 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/lemisky/article/details/102797821