如何爲Android系統添加一個新的資源包

傳統的Android系統只有一個framework-res.apk資源包,第三方廠商在進行rom定製時會直接修改framework res資源,達到美化目的。可是這種方式跟原生資源的耦合度太高,在系統遷移或者framework ui移植時須要進行人工merge,工做量巨大。經過爲Android添加一個新的獨立的資源包,能夠將廠商定製資源獨立出來,可移植、可維護性很是好。 java

具體作法能夠分爲如下幾個步驟: android

1. 修改build/core/clear_var.mk app

LOCAL_USE_LETV_FRAMEWORK_RES:= true ide

2. 修改build/core/package.mk ui

如下腳本能夠加在 $(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) this

以下所示: spa

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 code

在PRODUCT_PACKAGES增長letv-framework-res orm

4. 添加一個新的資源包項目,這裏在framework/base/core/res同級目錄下創建一個新的文件夾letv_res用來存放咱們的資源。把res目錄下的AndroidManifest.xml和Android.mk拷貝過來,進行修改。  xml

記得設置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>
相關文章
相關標籤/搜索