如何在AOSP中构建支持自定义命名空间的框架资源?
哈哈,这个需求其实完全可以照搬AOSP原生framework-res的玩法来实现,我帮你梳理一下具体的落地步骤,都是实战过的方案:
核心思路
我们需要构建两个核心模块:
- 一个自定义资源APK(类似
framework-res.apk),用来托管你的图片、字符串等资源,并通过指定的命名空间对外暴露; - 你的自定义框架静态JAR,依赖资源APK生成的R类,实现代码里的资源访问,最终两者都打包进
system.img。
具体实现步骤
1. 创建模块目录结构
在AOSP源码的frameworks/base下(或者单独的模块目录,比如packages/frameworks/mynamespace,看你的组织习惯)新建自定义框架的目录,结构参考:
mynamespace/ ├── Android.bp ├── AndroidManifest.xml ├── res/ │ ├── drawable/ # 存放自定义图片资源 │ ├── values/ │ │ ├── strings.xml # 自定义字符串 │ │ ├── public.xml # 固定资源ID,避免冲突 │ │ └── ids.xml # 自定义ID资源 │ └── ... # 其他资源目录(layout、color等) └── src/ └── com/ └── mynamespace/ └── framework/ # 你的自定义框架代码
2. 配置AndroidManifest.xml
这里的package字段就是你要的资源命名空间,比如你要@mynamespace/xxx的访问方式,直接设为mynamespace即可:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="mynamespace"> <application android:label="@string/app_name" /> </manifest>
3. 固定资源ID(public.xml)
一定要配置这个文件,否则每次编译资源ID会随机变化,导致其他模块引用失败。在res/values/public.xml里声明所有需要对外暴露的资源:
<public> <public type="string" name="app_name" id="0x7f010000" /> <public type="drawable" name="custom_icon" id="0x7f020000" /> <public type="id" name="custom_button" id="0x7f030000" /> </public>
注意ID段要避开系统资源(系统framework-res用0x01开头),自定义用0x7f开头就很安全。
4. 编写Android.bp构建脚本
这是实现打包的核心,要同时构建资源APK和静态JAR:
# 构建自定义资源APK(类似framework-res.apk) android_app { name: "mynamespace-res", manifest: "AndroidManifest.xml", resource_dirs: ["res"], # 只打包资源,不生成DEX dex_preopt: { enabled: false }, # 强制使用public.xml固定资源ID aaptflags: [ "--public-resources", "--auto-add-overlay", ], # 安装到system/framework目录,和系统资源包同路径 install_path: "/system/framework/", # 打包到system分区 product_specific: true, # 使用platform证书签名,系统级模块必须 certificate: "platform", } # 构建自定义框架静态JAR java_library_static { name: "mynamespace-framework", srcs: ["src/**/*.java"], # 依赖资源APK自动生成的R类库 static_libs: ["mynamespace-res-R"], # 依赖系统framework libs: ["framework"], # 安装到system/framework目录 installable: true, product_specific: true, }
这里的mynamespace-res-R是AOSP构建系统自动生成的R类库,包含R.mynamespace的层级结构,正好满足你代码里R.mynamespace.string.xxx的访问需求。
5. 配置系统打包到system.img
在你的设备/product的mk文件里(比如device/xxx/xxx/device.mk)添加以下配置,让编译系统自动把两个模块打包进system.img:
PRODUCT_PACKAGES += mynamespace-res mynamespace-framework # 如果要让所有系统应用都能直接访问这个框架,把它加到bootclasspath PRODUCT_BOOT_JARS += mynamespace-framework
验证资源访问
完成以上配置后,编译AOSP,你就能实现需求中的访问方式:
- 代码中访问:
// 获取字符串 String appName = context.getString(R.mynamespace.string.app_name); // 获取图片资源 Drawable icon = context.getDrawable(R.mynamespace.drawable.custom_icon); - 布局中访问:
<TextView android:text="@mynamespace/string/app_name" android:drawableLeft="@mynamespace/drawable/custom_icon" android:id="@mynamespace/id/custom_button" />
关键注意事项
- 资源ID必须通过
public.xml固定,否则跨编译版本的资源引用会失效; - 模块必须用
platform证书签名,否则无法安装到system分区; - 如果是给第三方应用提供访问,需要在应用的
AndroidManifest.xml中添加<uses-library>声明,或者把框架加到系统bootclasspath让所有应用默认可见。
内容的提问来源于stack exchange,提问作者Nasif Noorudeen
相关产品推荐
相关产品推荐

