读取 其他Apk 中的资源文件

1 篇文章 0 订阅
1 篇文章 0 订阅
如果是在做一些 主题 皮肤之类的功能.
很多都是把 相应主题的资源 放到 一个apk.
然后我们吧这个 apk 下载下来. 然后读取 这个apk 中的资源 镜像加载 ...

网上很常见的就是 下载下来这个apk 后需要 安装 才去加载这个 apk 的资源

其实还有一种 放开 可以 不用 安装这个apk 而且就能 加载这个apk 的资源,
而且 还能执行一些相应的方法...


如果是 安装了这个主题 apk 然后再加载 相应的资源 可以使用如下方法.

int id = resources.getIdentifier(name, "drawable", pkg);
通过传入  name , pkg 包名 就能得到 相应包名下 对应名字的资源文件.
然后就可以直接用了 

但是如果不安装 apk 该怎么使用呢?
由于 apk 没有安装我们就能很好的通过 res 直接过去相应的资源文件.
那么我们就需要 把这个apk 中的资源文件加载出来 … 

在网上看到了如下方法: 

    //这个方法把我们主题apk里的resource 加入到我们自己的主apk里的resource里
    //这个dexPath就是 我们theme.apk在 我们主apk 的存放路径
    private void addOtherResourcesToMain(String dexPath) {
        try {
            AssetManager assetManager = AssetManager.class.newInstance();
            //反射调用addAssetPath这个方法 就可以
            Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
            addAssetPath.invoke(assetManager, dexPath);
            mAssetManager = assetManager;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //把themeapk里的资源 通过addAssetPath 这个方法增加到本apk自己的path里面以后 就可以重新构建出resource对象了
        mResource = new Resources(mAssetManager, getResources().getDisplayMetrics(), getResources().getConfiguration());
    }

如果传入 apk 的路径 就可直接把 这个 apk 的res 加到我们的app 中来 
然后就可以通过  
int id = resources.getIdentifier(name, "drawable", pkg);
获取相应的资源文件...


下面在说说  执行 其他 apk 中的一些方法问题 
//是dex的输出路径(因为加载apk/jar的时候会解压出dex文件,这个路径就是保存dex文件的)
String optimizedDirectory = getCacheDir() + File.separator;
//DexClassLoader可以加载任何路径的apk/dex/jar 这里要注意了PathClassLoader只能加载/data/app中的apk,也就是已经安装到手机中的apk。
//这个也是PathClassLoader作为默认的类加载器的原因,因为一般程序都是安装了,
ClassLoader classLoader = new DexClassLoader(themeApkPath, optimizedDirectory, null, getClassLoader());
//把 theme apk 中的Res 加载进来
addOtherResourcesToMain(themeApkPath);

try {
    // 反射 执行 方法
    Class clazz = classLoader.loadClass("com.czy.themedemo.ThemeUtil");
    Method method = clazz.getMethod("getImg", Resources.class);
    Drawable drawable = (Drawable) method.invoke(null, mResource);
    LogUtil.d(TAG, "drawable = " + drawable);
    mImageView.setBackgroundDrawable(drawable);
} catch (Exception e) {
    LogUtil.d(TAG, "e = " + e.getMessage());
    e.printStackTrace();
}

其实就是 new 出一个 DexClassLoader 然后通过这个 class loader 去反射执行方法 
当然执行的方法不能 和 Context 这些 生命周期 有关的方法, 不然会出错.
不过有一点需要注意的是  
new DexClassLoader(themeApkPath, optimizedDirectory, null, getClassLoader()); 方法中 
optimizedDirectory  目录 必须是属于 该 app 本身的目录  即 context.getCacheDir() 这样的目录 不然会抛出异常

看一下 我上面执行的方法的源码吧: 
参考文章:



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值