android动态加载资源
来源:互联网 发布:淘宝网机械水压开关 编辑:程序博客网 时间:2024/06/05 09:18
android动态加载资源的一个典型的例子就是app的换肤功能。在应用中不可能将所有的皮肤内置到app中,特别是在一些节日里都会有新的皮肤上线,而且为了更新皮肤而更新整个应用也是不可能的。那么以apk插件的形式提供皮肤包,应用动态的加载的这些皮肤包提供的图片才是一种可取的方式。那么问题来了,要怎么动态加载这么皮肤包呢,需要处理两个方面:
- 获取插件包的resource
- 获取插件包的resource id
下面就从这两个方面说说怎么处理皮肤包。
1.获取插件包中的resource
一般我们获取resource实例的方法是直接使用context.getResource()获取的,现在要获取插件中的resource实例该方法就不适用了,我们来看看构造方法
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) { this(null); mResourcesImpl = new ResourcesImpl(assets, metrics, config, new DisplayAdjustments()); }
我们需要一个AssetManager的实例,如果直接实例话一个AssetManager类的话是不行的,它没有经过安装过程的处理,不能引用到一个应用中的资源。还好在AssetManager中有一个方法可以帮助我们做到这一点
/** * Add an additional set of assets to the asset manager. This can be * either a directory or ZIP file. Not for use by applications. Returns * the cookie of the added asset, or 0 on failure. * {@hide} */ public final int addAssetPath(String path) { return addAssetPathInternal(path, false); }
这是一个hide方法,这就需要调用反射的方式来调用这个方法。
AssetManager manager = AssetManager.class.newInstance(); Method addAssetMethod = manager.getClass().getMethod("addAssetPath", String.class); addAssetMethod.invoke(manager, apkPath);
2.获取插件包中的resource id
获取resource id就需要获取插件中的R类,如何获取插件中的R类呢?可以使用DexClassLoader这个类加载器,使用这个类就可以直接加载插件中的R类,并且都是static变量,可以非常方便的获取到resource id
DexClassLoader loader = new DexClassLoader(apkPath, codePath, null, this.getClass().getClassLoader());
3.实例
1.将插件apk放置到sdcard中
首先将一个apk作为插件放置到sdcard目录中作为插件供应用调用,apk中只放置了一张图片在drawable目录中。
2.应用中获取资源替换图片
package com.motiongear.simplecc.dynamicapk;import android.Manifest;import android.content.res.AssetManager;import android.content.res.Resources;import android.os.Bundle;import android.os.Environment;import android.support.v4.app.ActivityCompat;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.ImageView;import java.io.File;import java.lang.reflect.Field;import java.lang.reflect.Method;import dalvik.system.DexClassLoader;public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static final String APK_NAME = "app-debug.apk"; private ImageView mImageView; private Button mButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageView = (ImageView) this.findViewById(R.id.imageview); mButton = (Button) this.findViewById(R.id.btn); mButton.setOnClickListener(this); //获取动态权利,简单处理下 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0x001); } @Override public void onClick(View v) { String apkPath = Environment.getExternalStorageDirectory() + File.separator + APK_NAME; String codePath = getCodeCacheDir().getAbsolutePath(); DexClassLoader loader = new DexClassLoader(apkPath, codePath, null, this.getClass().getClassLoader()); try { //1. 获取resource id //加载插件中的R.drawable类 Class clz = loader.loadClass("com.motiongear.simplecc.pluginsapk.R$drawable"); //获取图片id Field field = clz.getDeclaredField("dog"); int resId = (int) field.get(clz); //2. 获取resource //实例化AssetManager AssetManager manager = AssetManager.class.newInstance(); Method addAssetMethod = manager.getClass().getMethod("addAssetPath", String.class); addAssetMethod.invoke(manager, apkPath); Resources superResource = getResources(); //获取插件的resource Resources pluginRes = new Resources(manager, superResource.getDisplayMetrics(), superResource.getConfiguration()); //替换图片 mImageView.setImageDrawable(pluginRes.getDrawable(resId)); } catch (Exception e) { e.printStackTrace(); } }}
显示结果如下:
阅读全文
0 0
- android动态加载资源
- Android——动态加载资源布局
- Android动态资源加载原理和应用
- Android动态资源加载原理和应用
- Android插件化之资源动态加载
- 动态加载资源文件
- 资源动态加载
- 资源的动态加载
- 动态加载资源
- 动态资源加载
- 动态资源加载
- 动态加载资源
- Unity3D-动态加载资源
- 动态加载资源
- Android Apk资源加载机制源码分析以及资源动态加载实现系列文章
- Android ListView,Gridview动态加载释放图片资源
- Android中利用“反射”动态加载R文件中的资源
- Android 动态加载 之 如何获取插件res资源
- docker run的--rm选项详解
- minmax()函数
- (一) Spring Boot学习笔记之第一个Spring Boot程序HelloWorld
- 网络编程实验3-并发多线程服务器设计
- Spring Boot项目利用Redis实现session管理
- android动态加载资源
- 五分钟读懂TCP 协议——TCP协议简介
- lua热更新
- pandas <十分钟掌握pandas常用操作>
- Integer Break
- NEUQ网络赛小结
- (4.3)uboot详解——异常和异常向量
- 在线算法和离线算法
- 一张思维导图,一篇文章看懂android学习之路