Android

资源管理和多国版本

资源是外部文件(不含代码的文件),它被代码使用并在编译时编入应用程序。Android支持不同类型的资源文件,包括XML,PNG以及JPEG文件XML文件根据描述的不同有不同格式。这份文档描述可以支持什么样的文件,语法,以及各种格式.

源代码以及XML文件将资源打包并编译进二进制文件,这种模式能使得资源更快得被加载。字符串也同样被压缩成更高效的模式。由于这些原因, Android平台上存在不同的资源类型.

这篇文档包含下列章节:

资源引用一起,这是一份完全技术性的文档,它包含了很多资源相关的信息。如果仅仅是使用Android平台不需要完全了解这份文档,当你需要时,再去了解它。

资源

这个主题包含了一个资源相关的术语列表,以及如何使用资源的例子。如果想看一个完整的资源类型查询,请查看 资源.

Android资源系统能跟踪所有非代码相关的应用程序。你可以使用 资源 类来访问应用程序的资源,资源的实例通常和应用程序联系在一起, 你可以通过Context.getResources()来访问。

应用程序的资源在编译时就被编译到应用程序二进制代码里。为了使用某个资源,你需要将它在代码目录结构里放正确,然后编译。作为编译过程的一 部分,产生的资源代号你可以在源代码里使用 -- 这允许编译器验证你的程序代码和你定义的资源是否相符。

下面的章节教你如何在应用程序代码里使用资源类.

创建资源

Android支持字符串,图片以及很多其他类型的资源。每个对象语法、格式以及它们存储位置的支持,都是取决于不同类型的对象? 通常,你可以通过三种类型的文件来创建资源:XML文件(除位图以及原数据文件),位图文件(对于图片)以及原始数据(其它类型,例如声音文件,等等。)。事实上,有两种不同类型的XML文件,一种是编译到包里的,另外一种是通过aapt来产生的资源文件, 这里有一张包含所有资源类型,文件格式,文件描述以及所有XML文件的详细信息的列表。

在项目里,你可以在子目录res/下创建和存储资源文件。Android有一个资源编译工具(aapt),它可以编译在这个 目录下所有的子目录中的资源,这里有个各种资源的列表。你可以从 资源引用 这里看到各种类型的对象,包含其语法以及格式。
路径 资源类型
res/anim/ XML文件被编译进 逐帧动画补间动画 的对象
res/drawable/

.png, .9.png, .jpg files 这些类型的文件被编译进下列这些图表资源列表

为了获得这些资源的类型,使用 Resource.getDrawable(id)

res/layout/ 可编译成屏幕布局的XML文件 (或者屏幕的一部分). 查看 布局
res/values/

可编译成多种类型资源的文件

注意: 不像其他 res/ 文件夹,它能容纳任何数量的文件,但只是描述其创建而不是资源本身. XML的元素类型可以决定这些资源在R.class里什么位置被替换 .

文件可以被命名为任何名字,文件夹里有一些典型的文件(一般约定文件以定义的元素类型后面部分为文件名)::

  • arrays.xml 定义数组
  • colors.xml 定义 颜色 颜色字串数值. 你可以使用Resources.getDrawable() 以及 Resources.getColor(), respectively, 取得这些资源.
  • dimens.xml 定义 尺寸数据 . 使用 Resources.getDimension() 取得这些资源。
  • strings.xml 定义字符串 数值 (使用 Resources.getStringResources.getText() 取得资源,(后者更好一点)getText() 能取到在用户界面上显示的文本框里的文本。
  • styles.xml 定义类型 对象。
res/xml/ 任何XML文件可以进行编译,并能在运行时调用Resources.getXML() 显示XML原文件。
res/raw/ 这里的任何文件都将直接被复制到设备上。编译产品时,这些数据不会被编译,它们被直接加入到程序包里。 为了在程序中使用这些资源,你可以调用Resources.openRawResource() , 参数为ID: R.raw.somefilename.

资源最终会被编译成APK文件,Android创建一个包装类,命名为R,这样你能做你的代码里使用这些资源类。 根据资源路径和文件名的不同,R包含很多子类。

全局资源

  • 一些资源类允许你定义颜色。它能接受多种网络类型的值 -- 你可以写成 #RGB, #ARGB, #RRGGBB, #AARRGGBB 这样16进制常数都可以。
  • 所有的颜色都可以设置一个阿尔法值,开始的两个16进制数指定为透明。 0在阿尔法值里意味着透明。当然,默认值 是不透明的。

使用资源

这个章节描述如果使用你创建的资源,它包含以下内容:

编译时,Android产生一个叫R的类,它指向你程序中所有的资源。这个类包含很多子类。每一种都是Android 支持的,同时,编译后会产生一个资源文件。每个类提供一个或多个编译后资源的标识符,你可以在代码中使用。下面是个 源代码的文件,里面包含了字符串,布局文件(全屏或者部分屏幕),以及图像资源。

注意: 这个R类是自动产生的,你不能手动编写。当资源变化的时候它会自动更新。

package com.android.samples;
public final class R {
    public static final class string {
        public static final int greeting=0x0204000e;
        public static final int start_button_text=0x02040001;
        public static final int submit_button_text=0x02040008;
        public static final int main_screen_title=0x0204000a;
    };
    public static final class layout {
        public static final int start_screen=0x02070000;
        public static final int new_user_pane=0x02070001;
        public static final int select_user_list=0x02070002;

    };
    public static final class drawable {
        public static final int company_logo=0x02020005;
        public static final int smiling_cat=0x02020006;
        public static final int yellow_fade_background=0x02020007;
        public static final int stretch_button_1=0x02020008;

    };
};

在代码中使用资源

只要知道资源的ID以及你编译进目标文件的资源类型就可以在代码里使用它来。下面是一些语法:

R.resource_type.resource_name

或者

android.R.resource_type.resource_name

resource_type是R子类的一种类型。 resource_name 是定义在XML文件里的资源名或者为其他文件类型定义的资源文件(没有后缀)名。 每种类型的资源会被加入到一个特定的R的子类中;为了学习哪种R的子类里有你编译的资源类型,参考资源引用 文档。被编译进应用程序的资源不需要 包的名字就可以直接被访问到(像这样:R.resource_type.resource_name). Android包含一些标准资源,如屏幕的类型,按钮的背景。要使用这些代码,你需要包含 android, 如 android.R.drawable.button_background.

这里有一些好的和糟糕的例子说明如何在代码里使用编译后的资源:

// 从画图资源类里装载一个当前屏幕背景。
this.getWindow().setBackgroundDrawableResource(R.drawable.my_background_image);

// 错误! 将一个资源ID装入一个需要字符串的方法中
this.getWindow().setTitle(R.string.main_title);

//正确!需要从资源封装类里取得标题。
this.getWindow().setTitle(Resources.getText(R.string.main_title));

// 从当前屏幕中装载布局数据。
setContentView(R.layout.main_screen);

//从ViewFlipper对象中设置动画中一帧 。
mFlipper.setInAnimation(AnimationUtils.loadAnimation(this, 
        R.anim.hyperspace_in));

// 在TextView对象中设置文本内容。	
TextView msgTextView = (TextView)findViewByID(R.id.msg);
msgTextView.setText(R.string.hello_message); 

资源引用

一个在属性(或者资源)里提供的数值可以被指向一个具体的资源。这常常被使用在布局文件中用于字符串(可以被本地化) 以及图片(存在于其他文件中的),通过一个引用可以是包括颜色和整数的任何资源类型。

例如,如果有 颜色资源, 我们可以将文本的颜色值 写在布局文件中,颜色值可以从资源文件里取得:

<?xml version="1.0" encoding="utf-8"?>
<EditText id="text"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:textColor="@color/opaque_red"
    android:text="Hello, World!" />

注意这里使用‘@’的前缀是说明资源引用 -- 后面的文本是资源的名字 @[package:]type/name. 这里我们不需要指定包,因为我们在我们自己的包里引用资源。 为了指定一个系统资源,你需要这样写:

<?xml version="1.0" encoding="utf-8"?>
<EditText id="text"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:textColor="@android:color/opaque_red"
    android:text="Hello, World!" />

另外一个例子,当你在布局文件里使用字符串,你必须做资源引用,这样字符串才能被使用:

<?xml version="1.0" encoding="utf-8"?>
<EditText id="text"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:textColor="@android:color/opaque_red"
    android:text="@string/hello_world" />

这段代码也能被用来创建资源间引用。例如,我们能这样创建图像资源:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <drawable id="my_background">@android:drawable/theme2_background</drawable>
</resources>

主题属性引用

另一种资源数值允许你引用当前主题属性值。这种属性引用只能被用于特殊的资源类以及XML属性中; 它允许你根据现在主题风格将你定制的UI变得更标准化,而不用使用大量的具体数值。

这里有个例子,我们能在布局文件中将文本颜色设置为基本系统主题中定义好的标准颜色:

<?xml version="1.0" encoding="utf-8"?>
<EditText id="text"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:textColor="?android:textDisabledColor"
    android:text="@string/hello_world" />

注意除来我们将前缀'?'代替了'@',其他非常像资源引用。当你使用这个标记,系统会自动查找你提供的属性的名字 -- 资源工具知道肯定会有资源属性相符合,你不需要详细指定(?android:attr/android:textDisabledColor).

使用资源标识符到主题里去寻找相应的数据而不是直接使用原数据,其语法和'@'模式是一样的: ?[namespace:]type/name 这里的type是可选择的.

使用系统资源

许多系统资源应用程序是可以使用的。这样的资源定义在"android.R"的类里。 例如,你可以使用下面的代码在屏幕 上显示一个标准的应用程序图标:

public class MyActivity extends Activity
{
    public void onStart() 
    {
        requestScreenFeatures(FEATURE_BADGE_IMAGE);

        super.onStart();

        setBadgeResource(android.R.drawable.sym_def_app_icon);
    }
}

用相似的方法,这段代码能将你的屏幕变成系统定义的标准的“绿色背景”:

public class MyActivity extends Activity
{
    public void onStart() 
    {
        super.onStart();

        setTheme(android.R.style.Theme_Black);
    }
}

对于不同的语言和设置支持不同的资源

你可以根据产品界面语言以及硬件配置设置不同的资源。注意,虽然你可以包含不同的字串,布局以及其他资源, 但开发包(SDK)不会给你显式的方法去指定不同的资源去加载。Android检测你的硬件以及位置信息选择合适的设置 去加载。用户可以到设备上的设置界面去选择不同的语言。

要包含不同的资源,在同一目录下创建并行的文件夹,在每个文件夹后加上合适的名字,这个名字能表明一些配置 信息(如语言,原始屏幕等等)。例如,这里的项目字符串文件一个是英文版的,另一个是法文版的:

MyApp/
    res/
        values-en/
            strings.xml
        values-fr/
            strings.xml

Android支持不同类型的修饰语,并可以加多条在文件夹名的后面, 修饰语之间以破折号分开。例如:一个绘图资源 类指定全部配置名称命名会像这样:

MyApp/
    res/
        drawable-en-rUS-port-160dpi-finger-keysexposed-qwerty-dpad-480x320/

更典型的,你可以仅仅指定部分特定的配置选项。只要保证所有的数值都是按顺序排列:

MyApp/
    res/
        drawable-en-rUS-finger/
        drawable-port/
        drawable-port-160dpi/
        drawable-qwerty/
?
修饰语
语言 两个小写字母 ISO 639-1。例如: en, fr, es
地区 两个大写字母加上一个小写字母'r' ISO 3166-1-alpha-2。 例如: rUS, rFR, rES
屏幕方向 port, land, square
屏幕像素 92dpi, 108dpi, 等等。
触摸屏类型 notouch, stylus, finger
键盘是否有效 keysexposed, keyshidden
基本文本输入模式 nokeys, qwerty, 12key
无触摸屏的主要
导航模式
notouch, dpad, trackball, wheel
屏幕分辨率 320x240, 640x480, 等等。大分辨率需要开始指定。

这个列表不包含一些特殊的参数,如载体,商标,设备/硬件,制造商。任何应用程序需要知道的信息都在资源修饰语里有说明。

这里有一些通用的关于资源目录的命名指导:

  • 各个变量用破折号分开 (每个基本的目录名后跟一个破折号)
  • 变量大小写敏感(其大小写法必须始终一致)
    例如,
    • 一个drawable 的目录必须命名为 drawable-port, 而不是drawable-PORT
    • 你不能有两个目录命名为 drawable-port 以及 drawable-PORT, 甚至故意将"port" 和 "PORT"指为不同的参数也不可以。
  • 一个式子里同一个类型修饰语中只有一个值是有效的(你不能指定像这样 drawable-rEN-rFR/)
  • 你可以指定多个参数去定义不同的配置,但是参数必须是上面表格里的。例如, drawable-en-rUS-land 意思在US-English的机器里载入风景视图。
  • Android会寻找最适合当前配置的目录,这会在下面描述
  • 表格里所列的参数是用来打破平衡以防止多重路径限制。 (看下面的例子)
  • 所有目录,无论是限制的,还是不限制的,只要在 res/ 目录下.一些目录是不能嵌套的(这样 res/drawable/drawable-en是不可以的)
  • 所有的资源在被代码引用中最好都使用简单的、不加修饰的名字,如果一个资源这样命名:
          MyApp/res/drawable-port-92dp/myimage.png
    它将这样被引用:
          R.drawable.myimage (code)
          @drawable/myimage (XML)

Android如何找到最合适的目录

Android将会挑出哪些基本资源文件在运行时会被使用,这依靠当前的配置。 选择过程如下:

  1. 删去一些和当前设备配置不符合的资源。例如,如果屏幕的像素是108dpi,这可以删除 MyApp/res/drawable-port-92dpi/.
    MyApp/res/drawable/myimage.png
    MyApp/res/drawable-en/myimage.png
    MyApp/res/drawable-port/myimage.png
    MyApp/res/drawable-port-92dpi/myimage.png
    
  2. 挑出一些最经常符合配置的资源。例如,如果我们的地区是 en-GB, 方向是 port,那我们有两个符合配置 的选项: MyApp/res/drawable-en/MyApp/res/drawable-port/. 这个目录 MyApp/res/drawable/ 可以被删除了,因为当另外一个有一次匹配正确,而它没有。
    MyApp/res/drawable/myimage.png
    MyApp/res/drawable-en/myimage.png
    MyApp/res/drawable-port/myimage.png
    
  3. 根据配置的优先级选取最终适合的文件,它们按顺利被排列在上面的表格里。更确切得说,语言匹配比方位匹配更重要, 所以我们可以通过选择语言文件来平衡, MyApp/res/drawable-en/.
    MyApp/res/drawable-en/myimage.png
    MyApp/res/drawable-port/myimage.png
    

术语

资源系统将一系列分散内容集合在一起形成最终的完整的资源功能,去帮助我们了解整个 系统。这里有一些核心概念以及组件的概要说明,你在开发中将可能使用到:

最终文件: 应用程序的独立的数据包。这包含所有从java程序编译成的目标文件,图像 (例如PNG图片), XML文件等等。这些文件以一种特定的方式组织在一起,在程序打包最后时,它们被打包成 一个独立的ZIP文件。

aapt: Android最终文件打包工具。这个工具产生最终程序的ZIP文件。除了将最终的元数据 文件打包在一起,它也解析资源定义到最终的二进制数据里。

资源表:aapt工具产生的特殊的文件,描述了所有在程序/包里的资源。这个文件可以通过 资源类来访问;它不能直接和应用程序接触。

资源: 资源表里一条记录描述的是单一的命名值。大体上, 资源分成两种:基本的和包装的.

资源标识符: 在资源表里所有的资源都被唯一的整数标识着。 所有的代码中(资源描述,XML 文件,Java源代码)你可以直接使用符号名代替真实的整数数值。

基本资源: 所有基本资源都可以被写成一个简单的字串,使用一定的格式可以描述资源 系统里各种不同的基本类型: 整数,颜色,字串,其他资源的引用,等等。像图片以及XML描述文件这些复杂资源, 被以基本字串资源储存,它们的值就是相关最终数据文件的路径。

包装资源: 有一种特殊类型的资源,不是简单的字符串,而是有一个随意的名字/数值配对列表。 每个数值可以对应它本身的资源标识,每个值可以持相同类型的字符串格式的数据作为一个正常的资源。包装资源支持 继承:一个包里的数据能从其他包里继承,有选择地替换或者扩展能产生你自己需要的内容。

种类: 资源种类是对于不同需求的资源标识符而言的。例如,绘制资源类常常实例化绘制类的对象,所以这些包含颜色以及指向图片或XML文件的字符串路径数据是原始数据。其它常见资源类型是字符串(本地化字符串),颜色(基本颜色),布局(一个指向XML文件的字串路径,它描述的是一个用户界面)以及风格(一个描述用户接口属性的包装资源)。还有一个标准的“attr”资源类型,它定义了命名包装数据以及XML属性的资源标识符。

风格: 包含包装资源类型的名字常常用来描述一系列用户接口属性。例如,一个TextView的类可能会有一个描述界面风格的类来定义文本大小,颜色以及对齐方式。在一个界面布局的XML文件中,可以使用“风格” 属性来确定整体界面风格,它的值就是风格资源的名字。

风格类: 这里将详述一些属性资源类。其实数据不会被放在资源表本身,通常在源代码里它以常量的形式出现,这也可以使你在风格类或者XML的标签属性里方便找到它的值。例如,Android平台里定义了一个“视图”的风格类,它包含所有标准视图的属性:画图区域,可视区域,背景等。这个视图被使用时,它就会借助风格类去从XML文件取得数据并将其载入到实例中。

配置: 对许多特殊的资源标识符,根据当前的配置,可以有多种不同的值。 配置包括地区(语言和国家),屏幕方向,屏幕分辨率,等等。当前的配置用来选择当资源表载入 时哪个资源值生效。

主题: 一个标准类型的资源能为一个特殊的上下文提供全局的属性值。 例如,当应用工程师写一个活动时,他能选择一个标准的主题去使用,白色的或者黑色的;这个类型 能提供很多信息,如屏幕背景图片/颜色,默认文本颜色,按钮类型,文本编辑框类型,文本大小,等。 当布置一个资源布局时,控件(文本颜色,选中后颜色,背景)的大部分设置值取自当前主题; 如果需要,布局中的风格以及属性也可以从主题的属性中获得。

覆盖层: 资源表不能定义新类型的资源,但是你可以在其他表里替换资源 值。就像配置值,这可以在装载时候进行;它能加入新的配置值(例如,改变字串到新的位置), 替换现有值(例如,将标准的白色背景替换成"Hello Kitty"的背景图片),修改资源包(例如修改主题 的字体大小。白色主题字体大小为18pt)。这实际上允许用户选择设备不同的外表,或者下载新的外表 文件。

资源引用

资源引用 这份文档提供了不同类型资源的详细列表,并提供了如何在Java代码中使用资源以及如何引用资源的 描述。

国际化和本地化

即将完成: 国际化和本地化是非常关键的,但现在的SDK还没有 完全支持好。当SDK成熟时, 这个章节会包含Android平台国际化和本地化的相关信息。 那时,外部字串以及良好的结构 将会使得创建和使用资源变得更省事。

jsjjms@126.com 2008-10-08