android资源的热更新(替换 AssetManager+LoadedApk中的资源路径)

原创 2016年08月31日 14:04:23

设置LoadedApk中的mResDir
创建AssetManager, 设置资源包路径
替换AssetManager


AssetManager newAssetManager = (AssetManager) AssetManager.class.getConstructor(new Class[0])
        .newInstance(new Object[0]);
Method mAddAssetPath = AssetManager.class.getDeclaredMethod("addAssetPath",
        new Class[] {
                String.class
        });
mAddAssetPath.setAccessible(true);
if (((Integer) mAddAssetPath.invoke(newAssetManager, new Object[] {
        externalResourceFile
})).intValue() == 0) {
    throw new IllegalStateException("Could not create new AssetManager");
}

Method mEnsureStringBlocks = AssetManager.class.getDeclaredMethod("ensureStringBlocks",
        new Class[0]);
mEnsureStringBlocks.setAccessible(true);
mEnsureStringBlocks.invoke(newAssetManager, new Object[0]);

if (activities != null)
    for (Activity activity : activities) {
        Resources resources = activity.getResources();
        try {
            Field mAssets = Resources.class.getDeclaredField("mAssets");
            mAssets.setAccessible(true);
            mAssets.set(resources, newAssetManager);
        } catch (Throwable ignore) {
            Field mResourcesImpl = Resources.class.getDeclaredField("mResourcesImpl");
            mResourcesImpl.setAccessible(true);
            Object resourceImpl = mResourcesImpl.get(resources);
            Field implAssets = resourceImpl.getClass().getDeclaredField("mAssets");
            implAssets.setAccessible(true);
            implAssets.set(resourceImpl, newAssetManager);
        }

        Resources.Theme theme = activity.getTheme();
        try {
            try {
                Field ma = Resources.Theme.class.getDeclaredField("mAssets");
                ma.setAccessible(true);
                ma.set(theme, newAssetManager);
            } catch (NoSuchFieldException ignore) {
                Field themeField = Resources.Theme.class.getDeclaredField("mThemeImpl");
                themeField.setAccessible(true);
                Object impl = themeField.get(theme);
                Field ma = impl.getClass().getDeclaredField("mAssets");
                ma.setAccessible(true);
                ma.set(impl, newAssetManager);
            }

            Field mt = ContextThemeWrapper.class.getDeclaredField("mTheme");
            mt.setAccessible(true);
            mt.set(activity, null);
            Method mtm = ContextThemeWrapper.class.getDeclaredMethod("initializeTheme",
                    new Class[0]);
            mtm.setAccessible(true);
            mtm.invoke(activity, new Object[0]);

            Method mCreateTheme = AssetManager.class.getDeclaredMethod("createTheme",
                    new Class[0]);
            mCreateTheme.setAccessible(true);
            Object internalTheme = mCreateTheme.invoke(newAssetManager, new Object[0]);
            Field mTheme = Resources.Theme.class.getDeclaredField("mTheme");
            mTheme.setAccessible(true);
            mTheme.set(theme, internalTheme);
        } catch (Throwable e) {
            Log.e("InstantRun",
                    "Failed to update existing theme for activity " + activity, e);
        }

        pruneResourceCaches(resources);
    }

Collection references;
if (Build.VERSION.SDK_INT >= 19) {
    Class resourcesManagerClass = Class.forName("android.app.ResourcesManager");
    Method mGetInstance = resourcesManagerClass.getDeclaredMethod("getInstance",
            new Class[0]);
    mGetInstance.setAccessible(true);
    Object resourcesManager = mGetInstance.invoke(null, new Object[0]);
    try {
        Field fMActiveResources = resourcesManagerClass
                .getDeclaredField("mActiveResources");
        fMActiveResources.setAccessible(true);

        ArrayMap arrayMap = (ArrayMap) fMActiveResources.get(resourcesManager);

        references = arrayMap.values();
    } catch (NoSuchFieldException ignore) {
        Field mResourceReferences = resourcesManagerClass
                .getDeclaredField("mResourceReferences");
        mResourceReferences.setAccessible(true);

        Collection references = (Collection) mResourceReferences.get(resourcesManager);
    }
} else {
    Class activityThread = Class.forName("android.app.ActivityThread");
    Field fMActiveResources = activityThread.getDeclaredField("mActiveResources");
    fMActiveResources.setAccessible(true);
    Object thread = getActivityThread(context, activityThread);

    HashMap map = (HashMap) fMActiveResources.get(thread);

    references = map.values();
}

for (WeakReference wr : references) {
    Resources resources = (Resources) wr.get();
    if (resources != null) {
        try {
            Field mAssets = Resources.class.getDeclaredField("mAssets");
            mAssets.setAccessible(true);
            mAssets.set(resources, newAssetManager);
        } catch (Throwable ignore) {
            Field mResourcesImpl = Resources.class.getDeclaredField("mResourcesImpl");
            mResourcesImpl.setAccessible(true);
            Object resourceImpl = mResourcesImpl.get(resources);
            Field implAssets = resourceImpl.getClass().getDeclaredField("mAssets");
            implAssets.setAccessible(true);
            implAssets.set(resourceImpl, newAssetManager);
        }

        resources.updateConfiguration(resources.getConfiguration(),
                resources.getDisplayMetrics());
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android热更新实现原理

最近Android社区的氛围很不错嘛,连续放出一系列的Android动态加载插件和热更新库,这篇文章就来介绍一下Android中实现热更新的原理。ClassLoader我们知道Java在运行时加载对应...
  • lzyzsd
  • lzyzsd
  • 2015年11月15日 01:31
  • 48522

android热更新机制

本文转自:http://dev.qq.com/topic/57a31921ac3a1fb613dd40f3 Android 不仅系统版本众多,机型众多,而且各个市场都各有各的政策和审...

Android 热更新 的使用

如今市场上有很多热更新的第三方,我使用的是阿里的阿里百川hotfix2.0,对于各种热更新的优劣我就不介绍了,网上很多,例如:http://www.jianshu.com/p/2d0f70e30111...

Android快速实现热更新

Bugly功能丰富,有应用更新(包括热更新和应用内的更新弹窗),bug上报统计,运营数据统计,内测分发四大功能.有后台管理功能. 1.集成腾讯Bugly SDK1.配置项目的gradle(添加插件依赖...

Android 热补丁技术——资源的热修复

今年真是热补丁框架的洪荒之力爆发的一年,短短时间内,已经出现了好几个热修复的框架了,基本上都是大同小异,这里我就不过多的去评论这些框架。只有自己真正的去经历过,你才会发现其中的坑。事实上,现在出现的大...

Android快速实现热更新

Bugly功能丰富,有应用更新(包括热更新和应用内的更新弹窗),bug上报统计,运营数据统计,内测分发四大功能.有后台管理功能. 1.集成腾讯Bugly SDK 1.配置项目的grad...

Android开发之assets目录下资源使用总结

因为系统在编译的时候不会编译assets下的资源文件,所以我们不能通过R.XXX.ID的方式访问它们。那我么能不能通过该资源的绝对路径去访问它们呢?因为apk安装之后会放在/data/app/**.a...

android app热更新方案探讨(三)

上期我们讨论了一些关于cordova的方面的知识,详细信息,还是以官网为准。这期,我们将继续探讨cordova方面的知识。至于如何创建cordova应用,开发文档上有详细的讲解,我们在次不讨论这个问题...

Android中assets目录和raw目录的区别和使用情况

原文作者: futurexiong 原文地址: http://my.eoe.cn/futurexiong/archive/5350.html 今天看到有人问Android中assets目录和ra...

Android 资源管理利器Resources和AssetManager介绍

Android如何加载第三方的资源,Resources与AssetManager获取资源的机制,本文教你如何快速了解...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android资源的热更新(替换 AssetManager+LoadedApk中的资源路径)
举报原因:
原因补充:

(最多只允许输入30个字)