赞
踩
做过Android Settings及Android原生应用开发的小伙伴们应该都知道,在其xml文件里面有根据product配置的选项,可以根据不同的product场景切换不同的资源。那么各位没有考虑过这些product的值是来自那里,以及怎么影响Settings或者其它使用product的App显示的呢?好吗,今天我将带领大伙解读一番,看看它的庐山真面!
注意:这里的Android版本是9,其它版本可能有一定差异。
在Android Settings开发里面,我们经常能看到这样的xml字符串定义,如下所示,通过product的值来匹配合适的string资源信息,那么这个product的值从何而来呢。当然不是从天上掉下来的,下面让我们一探究竟它到底来自何方!
<string name="bluetooth_pref_summary" product="tablet" msgid="3520035819421024105">"允许您的平板电脑与附近的蓝牙设备进行通信"</string>
<string name="bluetooth_pref_summary" product="device" msgid="2205100629387332862">"允许您的设备与附近的蓝牙设备进行通信"</string>
<string name="bluetooth_pref_summary" product="default" msgid="782032074675157079">"允许您的手机与附近的蓝牙设备进行通信"</string>
<string name="about_settings" product="tablet" msgid="593457295516533765">"关于平板电脑"</string>
<string name="about_settings" product="default" msgid="1743378368185371685">"关于手机"</string>
<string name="about_settings" product="device" msgid="6717640957897546887">"关于设备"</string>
<string name="about_settings" product="emulator" msgid="221313099578564438">"关于模拟设备"</string>
我想绝大部分的博客会说这个值是由ro.build.characteristics这个属性确定的,其实不然这个只是最终结果的表现,而product对应的值来最开始来源于于PRODUCT_CHARACTERISTICS所对应的赋值。有过Android源码build的应该知道,一般Android的编译配置都在build和device目录下面,让我们到改目录下面搜索一番,查看一下结果:
可以看到TARGET_AAPT_CHARACTERISTICS依赖于PRODUCT_CHARACTERISTICS,老规矩让我们搜一搜,看看它的来源:
可以看到ro.build.characteristics的值最终依赖TARGET_AAPT_CHARACTERISTICS的值。
通过前面的一番折腾,大家是不是对product从哪里来有了比较清晰的认识了。虽然不是很曲折,这边还是整理一下:
最后我们可以通过getprop查看一下这个属性的值:
xxx:/ # getprop ro.build.characteristics
default
不容易啊,搞清楚product的来龙去脉。到这里我想大家应该知道怎么修改product的值了,可以根据实际的项目配置修改device下面的PRODUCT_CHARACTERISTICS值达到最终确定product的值的目的。
好了,前面的章节解决了product从哪里来,那么这个章节就来看看product的值怎么影响Android原生App里面资源的编译了。
刚开始我以为,Android是通过ro.build.characteristics来决定选择那个字符串数据进行显示的,好吗后来才知道找个是多么的不靠谱啊,所以我搜索了framework目录,好吗一无所获。
不应该啊,为啥啥都没有。难道不是这个属性确定显示那个字符串吗。好吗,怪我当时短路了,不是这么回事的。
在前面的章节我们搜索TARGET_AAPT_CHARACTERISTICS有如下相关信息:
xxx@Ubuntu16-Model:~/ssd/qcom_64/msm8953-9$ grep -nr "TARGET_AAPT_CHARACTERISTICS" device/ build/
build/make/tools/buildinfo.sh:62:echo "ro.build.characteristics=$TARGET_AAPT_CHARACTERISTICS"
build/make/core/definitions.mk:2137: $(if $(filter --product,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --product ,$(PRIVATE_TARGET_AAPT_CHARACTERISTICS))) \
build/make/core/definitions.mk:2469: $(if $(filter --product,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --product , $(PRIVATE_TARGET_AAPT_CHARACTERISTICS))) \
build/make/core/prebuilt_internal.mk:659:$(my_res_package): PRIVATE_TARGET_AAPT_CHARACTERISTICS :=
build/make/core/product_config.mk:320: TARGET_AAPT_CHARACTERISTICS := default
build/make/core/product_config.mk:322: TARGET_AAPT_CHARACTERISTICS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CHARACTERISTICS))
build/make/core/static_java_library.mk:137:$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_AAPT_CHARACTERISTICS := $(TARGET_AAPT_CHARACTERISTICS)
build/make/core/static_java_library.mk:150:$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_AAPT_CHARACTERISTICS :=
build/make/core/Makefile:363: TARGET_AAPT_CHARACTERISTICS="$(TARGET_AAPT_CHARACTERISTICS)" \
build/make/core/package_internal.mk:353:$(R_file_stamp) $(my_res_package): PRIVATE_TARGET_AAPT_CHARACTERISTICS := $(TARGET_AAPT_CHARACTERISTICS)
build/make/core/package_internal.mk:520:$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_AAPT_CHARACTERISTICS := $(TARGET_AAPT_CHARACTERISTICS)
build/make/core/soong_config.mk:85:$(call add_json_str, AAPTCharacteristics, $(TARGET_AAPT_CHARACTERISTICS))
xxx@Ubuntu16-Model:~/ssd/qcom_64/msm8953-9$
让我们捋一捋,看看搜索到的信息,发现了一条有用的如下所示:
build/make/core/package_internal.mk:353:$(R_file_stamp) $(my_res_package): PRIVATE_TARGET_AAPT_CHARACTERISTICS := $(TARGET_AAPT_CHARACTERISTICS)
这个R_file_stamp不就和APK的编译有关系吗,顺着这条路让我们看看APK Build所依赖的build/core/package.mk文件,可以看到里面有依赖于package_internal.mk,如下所示:
xxx@Ubuntu16-Model:~/ssd/qcom_64/msm8953-9/build/core$ grep -nr "package_internal.mk" package.mk
64:include $(BUILD_SYSTEM)/package_internal.mk
77:include $(BUILD_SYSTEM)/package_internal.mk
在package_internal.mk可以看到LOCAL_BUILT_MODULE_STEM被定义为package.apk
xxx@Ubuntu16-Model:~/ssd/qcom_64/msm8953-9/build/core$ grep -nr "package.apk" package_internal.mk
239:LOCAL_BUILT_MODULE_STEM := package.apk.gz
242:LOCAL_BUILT_MODULE_STEM := package.apk
xxx@Ubuntu16-Model:~/ssd/qcom_64/msm8953-9/build/core$
而我们知道LOCAL_BUILT_MODULE与LOCAL_BUILT_MODULE_STEM有关系。在package_internal.mk可以看到LOCAL_BUILT_MODULE依赖于R_file_stamp,具体见如下所示:
# Other modules should depend on the BUILT module if
# they want to use this module's R.java file.
$(LOCAL_BUILT_MODULE): $(R_file_stamp)
而R_file_stamp会依赖resource_export_package,resource_export_package会做的动作有create-empty-package、add-assets-to-package等等:
ifdef LOCAL_EXPORT_PACKAGE_RESOURCES # Put this module's resources into a PRODUCT-agnositc package that # other packages can use to build their own PRODUCT-agnostic R.java (etc.) # files. resource_export_package := $(intermediates.COMMON)/package-export.apk $(R_file_stamp): $(resource_export_package) # add-assets-to-package looks at PRODUCT_AAPT_CONFIG, but this target # can't know anything about PRODUCT. Clear it out just for this target. $(resource_export_package): PRIVATE_PRODUCT_AAPT_CONFIG := $(resource_export_package): PRIVATE_PRODUCT_AAPT_PREF_CONFIG := $(resource_export_package): PRIVATE_RESOURCE_LIST := $(all_res_assets) $(resource_export_package): $(all_res_assets) $(full_android_manifest) $(rs_generated_res_zip) $(AAPT) @echo "target Export Resources: $(PRIVATE_MODULE) ($@)" $(create-empty-package) $(add-assets-to-package) endif $(LOCAL_BUILT_MODULE): $(R_file_stamp)
LOCAL_BUILT_MODULE做的动作有create-empty-package、add-assets-to-package、add-jni-shared-libs-to-package、add-dex-to-package、add-carried-java-resources、add-java-resources-to-package、sign-package、align-package等等。
$(LOCAL_BUILT_MODULE): PRIVATE_DONT_DELETE_JAR_DIRS := $(LOCAL_DONT_DELETE_JAR_DIRS)
$(LOCAL_BUILT_MODULE): PRIVATE_RESOURCE_INTERMEDIATES_DIR := $(intermediates.COMMON)/resources
$(LOCAL_BUILT_MODULE): PRIVATE_FULL_CLASSES_JAR := $(full_classes_jar)
$(LOCAL_BUILT_MODULE) : $(jni_shared_libraries)
$(LOCAL_BUILT_MODULE) : $(JAR_ARGS)
ifdef LOCAL_USE_AAPT2
$(LOCAL_BUILT_MODULE): PRIVATE_RES_PACKAGE := $(my_res_package)
$(LOCAL_BUILT_MODULE) : $(my_res_package) $(AAPT2) | $(ACP)
else
$(LOCAL_BUILT_MODULE): PRIVATE_RESOURCE_LIST := $(all_res_assets)
$(LOCAL_BUILT_MODULE) : $(all_res_assets) $(full_android_manifest) $(AAPT) $(ZIPALIGN)
endif # LOCAL_USE_AAPT2
好了经过这么一些套路的操作,大家应该知道其实product的影响是编译的时候根据TARGET_AAPT_CHARACTERISTICS来改变aapt打包时候决定的。这个流程有点繁琐,大家可以根据各自的Android版本自行研究。
build/make/core/package_internal.mk:353:$(R_file_stamp) $(my_res_package): PRIVATE_TARGET_AAPT_CHARACTERISTICS := $(TARGET_AAPT_CHARACTERISTICS)
下面我们将device下面的device/qcom/msm8953_64/msm8953_64.mk的PRODUCT_CHARACTERISTICS修改为tablet,如下所示:
diff --git a/device/qcom/msm8953_64/msm8953_64.mk b/device/qcom/msm8953_64/msm8953_64.mk
index c785f37..6c55481 100755
--- a/device/qcom/msm8953_64/msm8953_64.mk
+++ b/device/qcom/msm8953_64/msm8953_64.mk
@@ -113,7 +113,7 @@ DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE += \
device/qcom/msm8953_64/vendor_framework_compatibility_matrix.xml
# default is nosdcard, S/W button enabled in resource
-PRODUCT_CHARACTERISTICS := nosdcard
+PRODUCT_CHARACTERISTICS := tablet
此时我么通过make -j32 Settings重新编译Settings,然后推入终端看看终端的表现形式,就能说明是否是在编译打包时决定而不是运行时。
msm8953_64:/ # getprop ro.build.characteristics
device
<string name="about_settings" product="tablet" msgid="593457295516533765">"关于平板电脑"</string>
<string name="about_settings" product="default" msgid="1743378368185371685">"关于手机"</string>
<string name="about_settings" product="device" msgid="6717640957897546887">"关于设备"</string>
<string name="about_settings" product="emulator" msgid="221313099578564438">"关于模拟设备"</string>
修行至此,Android xml里面product的值来自哪里以及怎么影响编译已经播讲完毕了。我想对于Android xml中product的配置各位应该可以畅通无阻,来去无踪影了。此时的你可以一剑走天下了,为师的必杀器已经倾囊相授了。各位江湖见。
各位读者看官朋友们,Android xml里面product的值来自哪里以及怎么影响编译?已经全部完毕,希望能吸引你,激活发你的学习欲望和斗志。在最后麻烦读者朋友们如果本篇对你有帮助,关注和点赞一下,当然如果有错误和不足的地方也可以拍砖。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。