手动创建Context

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tanzui/article/details/85990403

项目需要在 Android shell 下执行 Java 代码,很多时候需要用到Context,不是常规的 Android 程序执行没办法直接获取到 Context 于是在经过一番阅读 Android 源码之后找到解决方案,手动创建一个Context。
先看 Context.java 的源码,发现是一个抽象类,具体实现是在 ContextImpl.java
创建 ContextImpl 的方法如下:

static ContextImpl createSystemContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null);
        context.setResources(packageInfo.getResources());
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetrics());
        return context;
    }

是一个私有静态方法,有一个 ActivityThread 参数,这样的话只需要反射得到它并给他一个参数就可以了
继续看 ActivityThread 的实现,发现有个静态方法 systemMain:

public static ActivityThread systemMain() {
        // The system process on low-memory devices do not get to use hardware
        // accelerated drawing, since this can add too much overhead to the
        // process.
        if (!ActivityManager.isHighEndGfx()) {
            ThreadedRenderer.disable(true);
        } else {
            ThreadedRenderer.enableForegroundTrimming();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
    }

只需要反射执行它就能拿到 ActivityThread 创建的实例,这样的话 获取 ContextImpl 的方法和参数都拿到了,只需要反射执行就可以了,代码如下:

				Looper.prepareMainLooper();
				
				Class<?> ActivityThread = Class.forName("android.app.ActivityThread");
				Method systemMain = ActivityThread.getDeclaredMethod("systemMain");
				
				Object object = systemMain.invoke(null);
				
				Class<?> ContextImpl  = Class.forName("android.app.ContextImpl");
				Method createSystemContext = ContextImpl.getDeclaredMethod("createSystemContext", ActivityThread);
				createSystemContext.setAccessible(true);
				Context contextInstace = (Context)createSystemContext.invoke(null, object);
				Context context = contextInstace.createPackageContext("com.tanzui.test", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);

猜你喜欢

转载自blog.csdn.net/tanzui/article/details/85990403