aosp_012.android系统资源

转自:https://blog.csdn.net/myfriend0/article/details/78840201

前言
在开发 APP 的时候,会在 res/ 下引入众多资源,但是有些资源是不需要引入的,因为 Android 系统已经提供了这些资源。所谓 Android 系统资源,就是 Android 系统自带的,可以供所有 APP 使用的资源。比如像 YES/NO 这种简单的字符串,可以直接引用 Android 系统自带的资源。

使用 Android 系统资源的好处:

减少开发成本。如对于国际化的 APP,往往需要翻译全球多种语言。引用 Android 资源,可减少翻译的成本。
减少设计成本。如 Android 资源提供了很多图像等资源,直接使用这些资源,可以省去设计图像、动画、颜色等的成本。
与系统风格保持一致。如 Android 系统的资源往往应用到系统主题等等,引用 Android 资源可以更好的保持 Android 倡导的设计。
读取系统配置。某些 Android 资源是 Android 系统功能的配置资源,如当前设备是否支持通话能力。
Android系统资源概述
一般情况下,Android 系统资源在 AOSP 的路径是:

frameworks/base/core/res/


一般情况下,Android 资源放置手机的位置是:

/system/framework/framework-res.apk


一般情况下,Android 资源在 SDK 中的路径是:

android-sdk/platforms/android-xx/data/res/
如:android-sdk/platforms/android-26/data/res/

Android系统资源权限分类
Android 系统资源分两种:

公开。即全局公开性,所有 APP 可便捷应用。
非公开。Android 系统对这些资源进行了一定性的隐藏,意在这些资源提供给Android系统工程所引用。但是 Android 不禁止 APP 去使用这些资源。
Android加载资源简介

è¿éåå¾çæè¿°
关系类图

è¿éåå¾çæè¿°
时序图


一般情况,一个 APP 可以加载 APP 本身打包编译的资源,可以加载 Android 系统资源,可以加载 APP overlay 资源。Android 系统是如何保证资源加载的准确性和安全性呢?在 Android 资源加载中,有一个资源路径概念,APP 只能加载资源路径下的资源。

如果确定资源路径?
资源加载从上下文 Context 开始,因此路径的设定也从 Context 的创建过程中进行设定。在创建 Context 的过程中,会创建 Resources 对象(创建Activity Context为例)。如下:

public @Nullable Resources createBaseActivityResources(@Nullable IBinder activityToken,
    @Nullable String resDir,。  //资源路径,一般为 APP 的资源,即 APP 安装路径
    @Nullable String[] splitResDirs,  //分离 APK 资源路径,现在的Android版本一般都不需要这个了
    @Nullable String[] overlayDirs,  //overlay资源路径,
    @Nullable String[] libDirs,
    .....) {
    try {
        Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#getResources");
        final ResourcesKey key = new ResourcesKey(
                resDir,
                splitResDirs,
                overlayDirs,
                libDirs,.....);
        classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
        //创建 Resources 对象
        return getOrCreateResources(activityToken, key, classLoader);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
    }
}


这个方法定义在文件 frameworks/base/core/java/android/app/ResourcesManager.java 中。

è¿éåå¾çæè¿°

请看上面代码中的注释。这里再看看 Resources 的创建过程,看看资源的路径是如何设定。


请特别注意上图中红色注释部分。

在上图中的 addAssetPath() 方法中,设置了 resDir、Split apk dir、overlayDir。但是没有设定 framework 的资源的,即 Android系统资源。可见,Android系统资源的路径并不在这里进行设定。由于 Android系统资源是面向所有 APP 的,因此每个 APP 都需要统一设定相同的路径,因此它的设定路径稍微有点不同。

设定 Android 系统资源路径


在上图中,在 createAssetManager() 方法中会创建 AssetManager 实例,在实例化过程中会设定 Android 系统资源路径。如下图:

è¿éåå¾çæè¿°
请特别注意上图中红色注释部分。


引用Android资源


在上面的章节Android加载资源简介中对 Android 资源的加载有了初步的认识,下面继续学习如何引用 Android 资源。

引用公开资源
Java代码中引用
String str = getResources().getString(android.R.string.yes);
1
xml代码中引用
android:text="@android:string/yes"
1
引用非公开资源
Java代码中引用

//params: 
// 1:res name
// 2:res type(string、bool、drawalbe...)
// 3:package(Android资源APK的包名为android)
int resId = getResources().getIdentifier("config_showNavigationBar", "bool", "android");
boolean isShowNav = getResources().getBoolean(resId);



在AOSP的源码中可以直接通过如下方式引用:

boolean isShowNav = getResources().getBoolean(com.android.internal.R.bool.config_showNavigationBar);


在APP工程使用这种方式会编译报错。

但是,不管是AOSP还是APP工程中,都不推荐第二种方式,因为有些厂商会对AOSP中的资源进行修改,此时 Android 资源的 res id 已经产生移位,当你用 SDK 中的 res id 去引用不同厂商的手机的 Android 资源时,可能会发生异常或者返回的结果并不是正确的结果。通过第一种方式,先获取 res id,然后再通过 res id 去获取资源,可以有效规避 res id 移位的问题。

xml代码中引用

android:enabled="@*android:bool/config_voice_capable"


在 xml 中引用 Android 系统非公开资源时,IDE 工具不会给你“代码提示”,因此需要你手动写完。且xml文件中会高亮标红,表示找不到该资源,但是不需要关心它,你可以正常编译和使用。xml中引用无法规避 res id 移位的问题


总结


在本文中学习中,学习了什么是 Android 系统资源,Android APP 加载资源的过程,APP 资源路径的确定过程,以及在 Java 和 xml 中如何引用 Android 系统资源。你可以在你的 Android SDK 目录中查看 Android 自带了那些资源,具体路径请查看第二章节Android系统资源概述。程序员不重复造轮子,能引用 Android 自带资源就用 Android 自带资源吧。
 

猜你喜欢

转载自blog.csdn.net/zzq1824837536/article/details/89334911
今日推荐