美文网首页插件化
VirtualApp的资源处理

VirtualApp的资源处理

作者: taoyyyy | 来源:发表于2019-12-27 13:53 被阅读0次

已知LoadedApk与Resource对象全局唯一,且其首次初始化是在初始化Application的时候。因此倘若我们能在初始化Application生成Context前替换掉LoadedApk对象中的资源路径,则后面拿到的Resource对象都会是插件apk对应的Resource.

com.lody.virtual.client.VClientImpl#bindApplicationNoCheck

    private void bindApplicationNoCheck(String packageName, String processName, ConditionVariable lock) {
        ...
        // 从 VPMS 获取 apk 信息
        data.appInfo = VPackageManager.get().getApplicationInfo(packageName, 0, getUserId(vuid));
       ...
        //首次创建Context
        Context context = createPackageContext(data.appInfo.packageName);
       ...
        //开始构建子程序包的 Application 对象,并且替换原来通过 Host Stub 生成的 mInitialApplication
        mInitialApplication = LoadedApk.makeApplication.call(data.info, false, null);
        mirror.android.app.ActivityThread.mInitialApplication.set(mainThread, mInitialApplication);
        ...
        try {
            //调用 Application.onCreate
            mInstrumentation.callApplicationOnCreate(mInitialApplication);
            ...
    }

咱们的套壳工程也是同样的思路,在壳工程Application#attachBasecontext中替换掉LoadedApk对象中的资源路径,此时插件工程的Application还未初始化。
TurnWorld#ProxyApplication

...
//替换Resources
ApplicationInfo applicationInfo = (ApplicationInfo)getObjectField(loadedApk,"mApplicationInfo");
applicationInfo.sourceDir = VirtualCore.getTargetCorePath();
ClassLoaderFixer.fixClassLoader(rClassLoader, applicationInfo.targetSdkVersion);
setObjectField(loadedApk, "mAppDir",VirtualCore.getTargetCorePath());
setObjectField(loadedApk, "mResDir",VirtualCore.getTargetCorePath());
//干掉宿主Application初识化时生成的mResources,以便下面替换掉LoadedApk中的资源路径后,调用LoadedApk#getResources能成功生成插件apk的Resource对象
setObjectField(loadedApk, "mResources", null);
Method getResource = null;
Resources resources = null;
if (Build.VERSION.SDK_INT <= N) {
    //生成插件apk的Resource对象
    getResource = loadedApk.getClass().getDeclaredMethod("getResources",currentThread.getClass());   
    resources = (Resources) getResource.invoke(loadedApk, currentThread);
} else {    
    getResource = loadedApk.getClass().getDeclaredMethod("getResources"); 
    getResource.setAccessible(true);   
    resources = (Resources) getResource.invoke(loadedApk);
 }
 setObjectField(contextImpl, "mResources", resources);
...

相关文章

网友评论

    本文标题:VirtualApp的资源处理

    本文链接:https://www.haomeiwen.com/subject/tahdoctx.html