[实战笔记]系统编译——新增客制化overlay资源包

前情提要:

[实战笔记]系统编译——新增客制化资源包_local_aapt_flags-CSDN博客

解决了新增资源包管理的问题。新的问题来了,如果需要用作overlay的文件,希望替换原有包里的资源,怎么解决?

1.直接使用link方案

直接添加新资源包,会发现编译报错。错误大概意思为:编译中发现有重名的资源。

2.为什么要用文件去替换原有包里的资源?而不是直接修改原有资源?

对于ROM定制来说,framework资源和自用资源是需要分离的,一个是降低对framework的修改,另一个是便于移植。

为了解决这种问题,Google官方其实已经提供了overlay的框架。使用这个框架之前,还是需要科普一下资源打包构建的基础知识。

aapt2

aapt2是Android提供的一种构建工具,会解析资源、为资源编制索引,并将资源编译为针对 Android 平台进行过优化的二进制格式。官方文档如下:

AAPT2  |  Android 开发者  |  Android Developers

简单来说,aapt2的执行分为编译和链接两个步骤。

编译

aapt2接受一个资源文件,并解析该文件生成一个扩展名为 .flat 的中间二进制文件

尝试使用aapt2进行编译:

aapt2路径:

android_sdk/build_tools/(sdk_version)/aapt2.exe

cmd或者使用powershell到这个路径下就可以执行aapt2命令了。

aapt2编译语法:

aapt2 compile path-to-input-files [options] -o output-directory/

一般在工程中的语法为:

aapt2 compile project_root/module_root/src/main/res/values-en/ strings.xml -o compiled/

在aapt2.exe的路径下放置名为ic_volume.png的资源,创建输出目录 compiled,简单尝试下编译:

aapt2 compile ic_volume.png -o compiled\

报错:

error: invalid file path 'ic_volume.png'

原因是所有的资源文件编译成中间二进制文件时都会编译成(resource-type)_name.flat,resource-type对应的是资源文件放置的目录path,即drawable/values/layout等,因此资源文件需要放在某个类型的目录中。

修改:

在aapt2.exe的路径下创建drawable目录,其中放置名为ic_volume.png的资源,创建输出目录 compiled,简单尝试下编译:

aapt2 compile drawable\ic_volume.png -o compiled\

在compiled目录中输出:drawable_ic_volume.png.flat

链接

aapt2 link -o output.apk
 -I android_sdk/platforms/android_version/android.jar
    compiled/res/values_values.arsc.flat
    compiled/res/drawable_Image.flat --manifest /path/to/AndroidManifest.xml -v

链接的过程会打包出apk,因此需要编译工具android.jar, apk中包含的AndroidManifest.xml,需要的flat文件。

创建目录 input, 将需要的资源都放在这个目录下,如某个工程中的AndroidManifest.xml,编译需要的资源目录drawable/ic_volume.png,然后执行命令试试看:

aapt2 link -o .\compiled\newApk.apk -I ..\..\platforms\android-33\android.jar .\compiled\drawable_ic_volume.png.flat --manifest .\input\AndroidManifest.xml -v
note: including ..\..\platforms\android-33\android.jar.
aapt2.exe W 10-08 12:04:54 13732  3156 LoadedArsc.cpp:657] Unknown chunk type '200'.
note: linking package 'com.tahlia.hmrefactormvvm' using package ID 7f.
note: merging 'drawable/ic_volume' from compiled file .\input\drawable\ic_volume.png.
note: enabling pre-O feature split ID rewriting.
.\input\AndroidManifest.xml:5: error: resource mipmap/ic_launcher (aka com.tahlia.hmrefactormvvm:mipmap/ic_launcher) not found.
.\input\AndroidManifest.xml:5: error: resource string/app_name (aka com.tahlia.hmrefactormvvm:string/app_name) not found.
.\input\AndroidManifest.xml:5: error: resource mipmap/ic_launcher_round (aka com.tahlia.hmrefactormvvm:mipmap/ic_launcher_round) not found.
.\input\AndroidManifest.xml:5: error: resource style/DefaultAppTheme (aka com.tahlia.hmrefactormvvm:style/DefaultAppTheme) not found.
error: failed processing manifest.

其中newApk.apk是希望生成的apk,android.jar是用于提供android命名空间的属性的包,drawable_ic_volume.png.flat是编译生成的中间二进制文件。

发现compiled目录下出现了newApk,但是里面是空的。查看上面打印,发现是因为一些资源找不到(因为没有给,只单独复制了某个工程的AndroidManifest.xml)。

于是将AndroidManifest.xml中说找不到的统统删除,重新试一次:

aapt2 link -o .\compiled\newApk.apk -I ..\..\platforms\android-33\android.jar .\compiled\drawable_ic_volume.png.flat --manifest .\input\AndroidManifest.xml -v
note: including ..\..\platforms\android-33\android.jar.
aapt2.exe W 10-08 12:06:46 13256  4516 LoadedArsc.cpp:657] Unknown chunk type '200'.
note: linking package 'com.tahlia.hmrefactormvvm' using package ID 7f.
note: merging 'drawable/ic_volume' from compiled file .\input\drawable\ic_volume.png.
note: enabling pre-O feature split ID rewriting.
AndroidManifest.xml: note: writing to archive (keep_raw_values=false).
note: writing AndroidManifest.xml to archive.
note: writing res/drawable/kk_ic_volume.png to archive.
note: writing resources.arsc to archive.

查看compiled目录下,已经生成newApk.apk,放入apkanalyzer,能看到正确内容:

 打包成功。

添加overlay资源包

overlay的优先级

Google针对overlay是声明了两种等级:

DEVICE_PACKAGE_OVERLAYS

PRODUCT_PACKAGE_OVERLAYS

从名字和AOSP的产品定义架构,不难看出,这两种定义的优先级为: DEVICE_PACKAGE_OVERLAYS > PRODUCT_PACKAGE_OVERLAYS。

而每一种overlay又可以接受多个路径,路径在前的优先级越高。例如下图:

即可得出overlay资源包的优先级为:

[DEVICE] device/xxxx/overlay > [DEVICE] vendor/xxxx/overlay/static > [DEVICE] device/xxxxx/overlay_res > [PRODUCT] (空)

overlay的声明定义

在AOSP中用上资源包,需要在mk/bp中声明添加。

在mk中添加:

# overlay
# DEVICE_PACKAGE_OVERLAYS += resPath
# PRODUCT_PACKAGE_OVERLAYS += resPath
DEVICE_PACKAGE_OVERLAYS += $(LOCAL_XXXX_PATH)/XXXX_res

bp暂时还没用到,使用androidmk转换一下就能出结果了。

overlay资源包添加遇到的问题

1.DEVICE_PACKAGE_OVERLAYS变量不可修改

在mk中定义了之后,编译出现如下问题:

FAILED: 
Android.mk:4: error: cannot assign to readonly variable: DEVICE_PACKAGE_OVERLAYS
15:33:14 ckati failed with: exit status 1

这个是因为 DEVICE_PACKAGE_OVERLAYS 需要配置好环境后才可以编辑,所以报错。也就是说这个mk调用的时间不合适,需要时机后移。

解决办法:可以放在其他mk中。针对这个情况我是放在了device下使用的mk。

2.multiple default products defined for resource

查看错误:

frameworks/base/core/res/res/values/strings.xml:3218: error: multiple default products defined for resource android:string/android_upgrading_title.
device/xxxx/overlay/frameworks/base/core/res/res/values/strings.xml:22: note: default product also defined here.

frameworks/base/core/res/res/values/strings.xml:3218: error: multiple default products defined for resource android:string/android_upgrading_title.
device/xxxx/overlay/frameworks/base/core/res/res/values/strings.xml:22: note: default product also defined here.

frameworks/base/core/res/res/values/strings.xml:3218: error: multiple default products defined for resource android:string/android_upgrading_title.
device/xxxx/overlay/frameworks/base/core/res/res/values/strings.xml:22: note: default product also defined here.

frameworks/base/core/res/res/values-zh-rCN/strings.xml:1191: error: multiple default products defined for resource android:string/android_upgrading_title.
device/xxxx/overlay/frameworks/base/core/res/res/values-zh-rCN/strings.xml:23: note: default product also defined here.

frameworks/base/core/res/res/values-zh-rTW/strings.xml:1191: error: multiple default products defined for resource android:string/android_upgrading_title.
device/txxxx/overlay/frameworks/base/core/res/res/values-zh-rTW/strings.xml:23: note: default product also defined here.

可以简单理解为重复定义。overlay实际上是对原有包中的资源进行覆盖的,因此是直接替换的原有资源,而无需定义。理论上overlay和framework不是一个等级的,继续排查。查看脚本:

out/soong/host/linux-x86/bin/aapt2 link 
-o out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/package-res.apk 
--private-symbols com.android.internal 
--no-auto-version 
--auto-add-overlay 
--no-static-lib-packages 
--manifest out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/manifest_fixer/AndroidManifest.xml 
-A frameworks/base/core/res/assets 
--min-sdk-version 29 
--target-sdk-version 29 
--version-code 29 
--version-name  10 
--product tv 
-c zh_CN,normal,large,xlarge,hdpi,xhdpi 
--preferred-density xhdpi 
--java out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/aapt2/R 
--proguard out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/proguard.options 
--output-text-symbols out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/R.txt @out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/aapt2/res.list 

-R @out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/aapt2/overlay.list && out/soong/host/linux-x86/bin/soong_zip -write_if_changed -jar -o out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/R.jar 
-C out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/aapt2/R 
-D out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/aapt2/R &&out/soong/host/linux-x86/bin/extract_jar_packages 
-i out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/gen/R.jar 
-o out/soong/.intermediates/frameworks/base/core/res/framework-res/android_common/extra_packages 
--prefix '--extra-packages'

找到-R的那部分是关于overlay的,查看overlay-list,发现里面也有google的overlay 不同语言string的记录,所以和string这个资源类别也没关系。

继续对比这个资源在AOSP中的定义和overlay中的定义,发现这个平台版本的资源是区分了product的,而我们在overlay中的并没有区分prodcut:

# AOSP中
<string name="android_upgrading_title" product="default"> xxxx </string>

# overlay中
<string name="android_upgrading_title"> xxxx </string>

解决方法:

资源声明是包括命名、产品几个区分维度的。ovrelay资源需要完全匹配资源的声明,否则就会报资源重复定义的错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值