文档章节

如何为Android系统添加一个新的资源包

Kingguary
 Kingguary
发布于 2013/11/19 16:05
字数 795
阅读 4295
收藏 13

传统的Android系统只有一个framework-res.apk资源包,第三方厂商在进行rom定制时会直接修改framework res资源,达到美化目的。但是这种方式跟原生资源的耦合度过高,在系统迁移或者framework ui移植时需要进行人工merge,工作量巨大。通过为Android添加一个新的独立的资源包,可以将厂商定制资源独立出来,可移植、可维护性非常好。

具体做法可以分为以下几个步骤:

1. 修改build/core/clear_var.mk

LOCAL_USE_LETV_FRAMEWORK_RES:= true

2. 修改build/core/package.mk

以下脚本可以加在 $(R_file_stamp): $(framework_res_package_export_deps) 之前,然后修改$(R_file_stamp): $(framework_res_package_export_deps) 和 $(LOCAL_INTERMEDIATE_TARGETS): \
    PRIVATE_AAPT_INCLUDES := $(framework_res_package_export)

如下所示:

ifeq ($(LOCAL_USE_LETV_FRAMEWORK_RES),true)
letv_framework_res_package_export := \
        $(call intermediates-dir-for,APPS,letv-framework-res,,COMMON)/package-export.apk
letv_framework_res_package_export_deps := \
        $(dir $(letv_framework_res_package_export))src/R.stamp
else
letv_framework_res_package_export :=
letv_framework_res_package_export_deps :=
endif # LOCAL_USE_LETV_FRAMEWORK_RES
$(R_file_stamp): $(framework_res_package_export_deps) $(letv_framework_res_package_export_deps)
$(LOCAL_INTERMEDIATE_TARGETS): \
    PRIVATE_AAPT_INCLUDES := $(framework_res_package_export) \
    	$(letv_framework_res_package_export)
endif # LOCAL_NO_STANDARD_LIBRARIES

3. 修改build/target/product/core.mk

在PRODUCT_PACKAGES增加letv-framework-res

4. 添加一个新的资源包项目,这里在framework/base/core/res同级目录下建立一个新的文件夹letv_res用来存放我们的资源。把res目录下的AndroidManifest.xml和Android.mk拷贝过来,进行修改。 

记得设置LOCAL_USE_MY_FRAMEWORK_RES为false。

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_PACKAGE_NAME := letv-framework-res
LOCAL_CERTIFICATE := platform

# Set LOCAL_USE_LETV_FRAMEWORK_RES as false
LOCAL_USE_LETV_FRAMEWORK_RES := false

# Tell aapt to create "extending (non-application)" resource IDs,
# since these resources will be used by many apps.
LOCAL_AAPT_FLAGS := -x

# Install this alongside the libraries.
LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)

# Create package-export.apk, which other packages can use to get
# PRODUCT-agnostic resource data like IDs and type definitions.
LOCAL_EXPORT_PACKAGE_RESOURCES := true

# Include resources generated by system RenderScript files.
framework_GENERATED_SOURCE_DIR := $(call intermediates-dir-for,JAVA_LIBRARIES,framework,,COMMON)/src
framework_RenderScript_STAMP_FILE := $(framework_GENERATED_SOURCE_DIR)/RenderScript.stamp
#LOCAL_RESOURCE_DIR := $(framework_GENERATED_SOURCE_DIR)/renderscript/res $(LOCAL_PATH)/res

include $(BUILD_PACKAGE)

# Make sure the system .rs files get compiled before building the package-export.apk.
#$(resource_export_package): $(framework_RenderScript_STAMP_FILE)

# define a global intermediate target that other module may depend on.
.PHONY: letv-framework-res-package-target
letv-framework-res-package-target: $(LOCAL_BUILT_MODULE)


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="letv" coreApp="true" android:sharedUserId="android.uid.system"
    android:sharedUserLabel="@null">

    <application android:process="system"
                 android:persistent="true"
                 android:hasCode="false"
                 android:label="@null"
                 android:allowClearUserData="false"
                 android:killAfterRestore="false"
                 android:icon="@null">

    </application>

</manifest>


资源的放置跟res下的类似,记得values目录下创建public.xml,public.xml对id的类型区分比较严格,attr必须是0x0x010000开头,drawable必须是0x0x020000开头,其他类型好像就没有限制,直接依次0x0x030000、0x0x040000开始即可。否则,编译过程中会出现segmentation fault错误。

<resources>
 <public type="attr" name="cForeground" id="0x03010000" />
 <public type="drawable" name="ic_filemanager" id="0x03020000" />
 <public type="style" name="LetvTheme" id="0x03030000" />
 <public type="string" name="letv" id="0x03040000" />
 <public type="dimen" name="letv_width" id="0x03050000" />
 <public type="layout" name="letv_text" id="0x03060000" />
</resources>
5.  以上只是解决了资源的编译环境问题,资源的查找过程也需要进行修改,修改 AssetManager.java,在init()后添加代码 addAssetPath("/system/framework/letv-framework-res.apk");
public AssetManager() {
        synchronized (this) {
            if (DEBUG_REFS) {
                mNumRefs = 0;
                incRefsLocked(this.hashCode());
            }
            init();
            addAssetPath("/system/framework/letv-framework-res.apk");
            if (localLOGV) Log.v(TAG, "New asset manager: " + this);
            ensureSystemAssets();
        }
    }


6. 最后就是资源应用问题。应用程序在xml文件中引用letv-framework-res.apk中的资源时可以使用与原生资源类似的访问方式,首先声明letv xmlns :

xmlns:letv="http://schemas.android.com/apk/res/letv"

然后像@android:drawable @android:dimen这种引用方式改成@letv:drawable @letv:dimen即可。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:letv="http://schemas.android.com/apk/res/letv"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:paddingTop="@letv:dimen/letv_width"
    android:orientation="horizontal" >

   <ImageView android:id="@+id/file_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginBottom="40dp"
            android:src="@letv:drawable/ic_filemanager" />

</LinearLayout>

© 著作权归作者所有

Kingguary
粉丝 11
博文 71
码字总数 21482
作品 0
海淀
私信 提问
加载中

评论(10)

杜鹏宙
杜鹏宙
您好,博主,请问一下,有demo吗?
李贰
李贰
你好,这里有个疑问。关于编译之后的资源应用问题,您只是提到了在xml中的,在实际代码中呢是怎么使用的
鱼小念
鱼小念
18 发生了 xml里面调不到,只能在java文件中使用的情况。。。。
杜鹏宙
杜鹏宙
您好,我也发生了 xml里面调不到,只能在java文件中使用的情况,您最后解决了吗?
n
niesy
请问你在android 5.0上试过吗,我在5.0上添加新的资源包遇到了一些问题。
Kingguary
Kingguary 博主

引用来自“鱼小念”的评论

为什么我添加了 public 里面的东西 在编译的时候出现段错误
应该是type对应的数字有问题
鱼小念
鱼小念
为什么我添加了 public 里面的东西 在编译的时候出现段错误
iptvphone
iptvphone
mark
liujianganggood
liujianganggood
按照楼主的方法,编译的时候我报了一个错误,望楼主能回复,非常感谢!!
frameworks/base/core/launcher_res/AndroidManifest.xml:20: error: No resource identifier found for attribute 'sharedUserId' in package 'android'
java9
java9
mark
Android 插件化 01 —— 小实验

目的:用最简单的方法调用起指定apk(未安装过)中的Activity 困难: apk没有安装,就无法使用startActivity调起apk中指定的Activity,不管是显式调用还是隐式调用,都不行。 解决思路: 既然...

飛飛萨
2017/06/03
0
0
Android 资源调用 Accessing Resource

Accessing Resource 译者署名:CodeGuy 译者链接:http://www.cnblogs.com/CodeGuy/ 版本:Android 3.2 r1 原文 http://developer.android.com/guide/topics/resources/accessing-resources.......

阿酷
2011/11/17
354
0
从0系统学Android--1.3创建你的第一个 Android 项目

从0系统学Android--1.3创建你的第一个 Android 项目 1.3 创建你的第一个 Android 项目 环境搭建完成后,我们就可以写下我们的第一个项目了。 1.3.1 创建 HelloWorld 项目 在 Android Studio...

优惠券发放
07/21
0
0
Android应用开发中的风格和主题(style,themes)

当你设计你的程序的时候,你可以用风格和主题来统一格式化各种屏幕和UI元素。 风格是一个包含一种或者多种格式化属性的集合,你可以将其用为一个单位用在布局XML单个元素当中。比如,你可以定...

红薯
2009/06/29
34.3K
16
Android Intents和Intent过滤器(一)

Android应用程序有三个核心组件---Activity、Service、Broadcast Receiver,Broadcast receiver是通过叫做Intent的消息来激活的。Intent消息是同一个应用程序或不同应用程序运行后,组件间进...

长平狐
2012/10/16
143
0

没有更多内容

加载失败,请刷新页面

加载更多

Rust 的 GUI 框架生态概览

本文比较全面比较了目前主流的 Rust 的 GUI 框架的表现。其中 ++ 表示非常好,-- 表示非常差,而 o 表示处于平均水平。 参与对比的框架共有 8 个,详细的比较结果如下: Electron + Neon El...

红薯
12分钟前
2
0
golang微服务框架go-micro 入门笔记2.1 micro工具之micro api

micro api micro 功能非常强大,本文将详细阐述micro api 命令行的功能 重要的事情说3次 本文全部代码https://idea.techidea8.com/open/idea.shtml?id=6 本文全部代码https://idea.techidea8....

非正式解决方案
今天
2
0
Spring Context 你真的懂了吗

今天介绍一下大家常见的一个单词 context 应该怎么去理解,正确的理解它有助于我们学习 spring 以及计算机系统中的其他知识。 1. context 是什么 我们经常在编程中见到 context 这个单词,当...

Java知其所以然
昨天
3
0
Spring Boot + Mybatis-Plus 集成与使用(二)

前言: 本章节介绍MyBatis-Puls的CRUD使用。在开始之前,先简单讲解下上章节关于Spring Boot是如何自动配置MyBatis-Plus。 一、自动配置 当Spring Boot应用从主方法main()启动后,首先加载S...

伴学编程
昨天
7
0
用最通俗的方法讲spring [一] ──── AOP

@[TOC](用最通俗的方法讲spring [一] ──── AOP) 写这个系列的目的(可以跳过不看) 自己写这个系列的目的,是因为自己是个比较笨的人,我曾一度怀疑自己的智商不适合干编程这个行业.因为在我...

小贼贼子
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部