由Resource的构造函数Resources(AssetManager assets, DisplayMetrics metrics, Configuration config)了解到,需要获取app外部apk文件资源的Resource对象,首先需要创建对应的AssetManager对象。

public final class AssetManager implements AutoCloseable {
/**
* Create a new AssetManager containing only the basic system assets.
* Applications will not generally use this method, instead retrieving the
* appropriate asset manager with {@link Resources#getAssets}. Not for
* use by applications.
* {@hide}
*/
public AssetManager() {
synchronized (this) {
if (DEBUG_REFS) {
mNumRefs = 0;
incRefsLocked(this.hashCode());
}
init(false);
if (localLOGV) Log.v(TAG, "New asset manager: " + this);
ensureSystemAssets();
}
}
/**
* 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}
*/
//添加额外的asset路径
public final int addAssetPath(String path) {
synchronized (this) {
int res = addAssetPathNative(path);
if (mStringBlocks != null) {
makeStringBlocks(mStringBlocks);
}
return res;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
所以通过反射可以创建对应的AssertManager,进而创建出对应的Resource实例,代码如下:

private final static Resources loadTheme(String skinPackageName, Context context){
String skinPackagePath = Environment.getExternalStorageDirectory() + "/" + skinPackageName;
File file = new File(skinPackagePath);
Resources skinResource = null;
if (!file.exists()) {
return skinResource;
}
try {
//创建AssetManager实例
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
addAssetPath.invoke(assetManager, skinPackagePath);
//构建皮肤资源Resource实例
Resources superRes = context.getResources();
skinResource = new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());

} catch (Exception e) {
skinResource = null;
}
return skinResource;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2、如何知道当前属性值在所在Resource中的id
在Resource的源码中,可以发现

public class Resources {
/**
* 通过给的资源名称,类型和包名返回一个资源的标识id。
* @param name 资源的描述名称
* @param defType 资源的类型名称
* @param defPackage 包名
*
* @return 返回资源id,0标识未找到该资源
*/
public int getIdentifier(String name, String defType, String defPackage) {
if (name == null) {
throw new NullPointerException("name is null");
}
try {
return Integer.parseInt(name);
} catch (Exception e) {
// Ignore
}
return mAssets.getResourceIdentifier(name, defType, defPackage);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
也就是说在任意的apk文件中,只需要知道包名(manifest.xml中指定的包名,用于寻找资源和Java类)、资源类型名称、资源描述名称。
比如:在包A中有一个defType为"color",name为color_red_1的属性,通过Resource#getIdentifier则可以获取包B中该名称的颜色资源。

//将skina重View的背景色设置为com.example.skinb中所对应的颜色
if (attrValue.startsWith("@") && attrName.contains("background")){
int resId = Integer.parseInt(attrValue.substring(1));
int originColor = mContext.getResources().getColor(resId);
if (mResource == null){
return originColor;
}
String resName = mContext.getResources(http://www.my516.com).getResourceEntryName(resId);
int skinRealResId = mResource.getIdentifier(resName, "color", "com.example.skinb");
int skinColor = 0;
try{
skinColor = mResource.getColor(skinRealResId);
}catch (Exception e){
Log.e(TAG, "", e);
skinColor = originColor;
}
view.setBackgroundColor(skinColor);
}
---------------------

如何创建自定义的Resource实例的更多相关文章

  1. 在vue中创建自定义指令

    原文:https://dev.to/ratracegrad/creating-custom-directives-in-vue-58hh 翻译:心上有杨 指令是带有 v- 前缀的特殊属性.指令的作用是 ...

  2. sharepoint2010 创建自定义列表

    转:http://boke.25k5.com/kan77298.html 如何创建自定义列表 首先了解创建自定义列表中涉及到的几个名词:栏.内容类型. ①栏:栏即列.字段(Field),MSDN中给出 ...

  3. ASP.NET MVC随想录——创建自定义的Middleware中间件

    经过前2篇文章的介绍,相信大家已经对OWIN和Katana有了基本的了解,那么这篇文章我将继续OWIN和Katana之旅——创建自定义的Middleware中间件. 何为Middleware中间件 M ...

  4. 带你走近AngularJS - 创建自定义指令

    带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自定义指令 ------------- ...

  5. HTML5 UI框架Kendo UI Web中如何创建自定义组件(二)

    在前面的文章<HTML5 UI框架Kendo UI Web自定义组件(一)>中,对在Kendo UI Web中如何创建自定义组件作出了一些基础讲解,下面将继续前面的内容. 使用一个数据源 ...

  6. angularjs 创建自定义的指令

    创建自定义的指令 除了 AngularJS 内置的指令外,我们还可以创建自定义指令. 你可以使用 .directive 函数来添加自定义的指令. 要调用自定义指令,HTMl 元素上需要添加自定义指令名 ...

  7. javascript创建自定义对象和prototype

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. JavaScript之面向对象学习七(动态原型模式、寄生构造函数模式、稳妥构造函数模式创建自定义类型)

    一.动态原型模式 在面向对象学习六中的随笔中,了解到组合构造函数模式和原型模式创建的自定义类型可能最完善的!但是人无完人,代码亦是如此! 有其他oo语言经验的开发人员在看到独立的构造函数和原型时,很可 ...

  9. 创建自定义的Middleware中间件

    创建自定义的Middleware中间件 阅读目录 何为Middleware中间件 使用Inline方式注册Middleware 使用Inline+ AppFunc方式注册Middleware 定义原生 ...

随机推荐

  1. vue组件生命周期

    分为4个阶段:create/mount/update/destroy 每一个阶段都对应着有自己的处理函数 create: beforeCreate created 初始化 mount: beforeM ...

  2. TensorFlow学习笔记6-数值计算基础

    TensorFlow学习笔记6-数值计算 本笔记内容为"数值计算的基础知识".内容主要参考<Deep Learning>中文版. \(X\)表示训练集的矩阵,其大小为m ...

  3. 应用安全 - 代码审计 -Java

    Java %c0%ae 安全模式绕过漏洞 原理 在Java端"%c0%ae"解析为"\uC0AE",最后转义为ASCCII低字符-".".通 ...

  4. 排序算法六:计数排序(Counting sort)

    前面介绍的几种排序算法,都是基于不同位置的元素比较,算法平均时间复杂度理论最好值是θ(nlgn). 今天介绍一种新的排序算法,计数排序(Counting sort),计数排序是一个非基于比较的线性时间 ...

  5. PyTorch笔记之 Dataset 和 Dataloader

    一.简介 在 PyTorch 中,我们的数据集往往会用一个类去表示,在训练时用 Dataloader 产生一个 batch 的数据 https://pytorch.org/tutorials/begi ...

  6. [Python3 填坑] 006 “杠零”,空字符的使用

    目录 1. print( 坑的信息 ) 2. 开始填坑 2.1 \0 是空字符,输出时看不到它,但它占 1 个字符的长度 2.2 \0 "遇八进制失效" 2.3 \0 与 '' 不 ...

  7. Java中的容器(集合)

    1.Java常用容器:List,Set,Map List: 继承了Collection接口(public interface List<E> extends Collection<E ...

  8. void die(const char *msg)

    void die(const char *msg) { perror(msg); exit(errno); }

  9. 修复线上bug

    1,git branch new_branch 2,git push origin new_branch 以上是线上地址操作,以下是本地仓库操作 3,git fetch 4,git checkout ...

  10. OtterTune源码解析

    为了方便后面对ottertune进行魔(hu)改(gao),需要先搞清楚它的源码结构和pipeline OtterTune分为两大部分: server side: 包括一个MySQL数据库(用于存储调 ...