資源文件是在代碼中使用到的并且在編譯時被打包到應用程序的附加文件。Android支持多種不同的文件,包括XML、PNG和JPEG文件。而Android平臺中會存在很多不同的資源和資源定義文件。每一種資源定義文件的語法和格式及保存的位置取決于其依賴的對象。通常,創(chuàng)建資源可以通過以下3種文件:XML文件(除位圖和原始格式文件外),位圖文件(作為圖片)和原始格式文件(所有其他的類型,比如聲音文件)。
XML(eXtensible Markup Language),主要用來存儲數(shù)據(jù),使得其易于在任何應用程序中讀寫數(shù)據(jù),雖然不同的應用軟件也可以支持它的數(shù)據(jù)交換格式。事實上,在Android程序中有兩種不同類型的XML文件:一種是作為資源被編譯進應用程序;另一種是作為資源的描述,被應用程序使用。表7-2詳細說明了這些資源文件的類型和結構。
表7-2 資源文件
目錄 |
資源類型 |
res/anim |
XML文件編譯為楨序列動畫或者自動動畫對象 |
res/drawable |
使用Resources.getDrawable(id)可以獲得資源類型。png、9.png、.jpg文件被編譯為Drawable資源子類型:
* 位圖文件。
* 9-patchs(可變位圖文件)
|
res/layout |
資源編譯為屏幕布局器 |
res/values |
XML 文件可以被編譯為多種資源
注意:不像其他res下的目錄,這個目錄可以包含多個資源描述文件。XML文件元素類型控制著這些資源被R類放置在何處。
這些文件可以自定義名稱。這里有一些約定俗成的文件:
* arrays.xml 定義數(shù)組。
* colors.xml 定義可繪制對象的顏色和字符串的顏色。使用Resources.getDrawable()和Resources.getColor()都可以獲得這些資源。
* dimens.xml 定義尺度。使用Resources.getDimension()可以獲得這些資源。
* strings.xml 定義字符串(使用Resources.getString()或者更適合的Resources.getText()方法獲得這些資源。Resources.getText()方法將保留所有用于描述用戶界面樣式的描述符,保持復雜文本的原貌。
* styles.xml 定義樣式對象
|
res/xml |
自定義的XML文件。這些文件將在運行時編譯進應用程序,并且使用Resources.getXML()方法可以在運行時獲取 |
res/raw |
自定義的原始格式資源,將被直接復制給設備。這些文件將不被壓縮至應用程序。使用帶有ID參數(shù)的Resources.getRawResource()方法可以獲得這些資源,比如R.raw.somefilename |
由表7-2可看出,有多種不同的XML文件,XML文件描述的內容不同則決定了其不同的格式。這些文件將描述文件支持的類型、語法或格式等。
下面我們就通過ResourceFileDemo示例來了解如何在程序運行時訪問資源文件。ResourceFileDemo示例用戶界面如圖7-7所示。

圖7-7 ResourceFileDemo示例用戶界面圖
在圖7-7所示界面中,當用戶單擊“讀取原始文件”按鈕時,程序將讀取/res/raw/raw_file.txt文件,并將內容顯示在界面上。當用戶單擊“讀取XML文件”按鈕時,程序將讀取/res/xml/people.xml文件,并將內容顯示在界面上。
讀取原始格式文件,首先需要調用getResource()方法獲得資源對象,其次通過調用資源對象的openRawResource()方法,以二進制流的形式打開指定的原始格式文件。在讀取文件結束后,調用close()方法關閉文件流。
ResourceFileDemo示例中關于讀取原始格式文件的核心代碼如代碼清單7-18所示。
代碼清單7-18 ResourceFileDemo示例讀取原始格式文件核心代碼
Resources resources = this.getResources();
InputStream inputStream = null;
try {
inputStream = resources.openRawResource(R.raw.raw_file);
byte[] reader = new byte[inputStream.available()];
while (inputStream.read(reader) != -1) {
}
//以UTF-8的編碼方式,從字節(jié)數(shù)組中實例化一個字符串
displayView.setText(new String(reader,"utf-8"));
} catch (IOException e) {
Log.e("ResourceFileDemo", e.getMessage(), e);
} finally {
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) { }
}
}
下面介紹一下如何在程序運行時讀取/res/xml目錄下的XML文件。
首先,在/res/xml目錄下創(chuàng)建一個名為people.xml的文件,XML文件定義了多個<person>元素,每個<person>元素都包含三個屬性name、age和height,分別表示姓名、年齡和身高。/res/xml/people.xml文件代碼如代碼清單7-19所示。
代碼清單7-19 people.xml
<people>
<person name="李某某" age="21" height="1.81" />
<person name="王某某" age="25" height="1.76" />
<person name="張某某" age="20" height="1.69" />
</people>
然后,讀取XML格式文件。通過調用資源對象的getXml()方法,獲取到XML解析器XmlPullParser,XmlPullParser是Android平臺標準的XML解析器,這項技術來自一個開源的XML解析API項目XMLPULL。ResourceFileDemo示例中關于讀取XML文件的核心代碼如代碼清單7-20所示。
代碼清單7-20 ResourceFileDemo示例讀取XML文件的核心代碼
//通過資源對象的getXml()方法獲取到XML解析器
XmlPullParser parser = resources.getXml(R.xml.people);
String msg = "";
try {
//parser.next()方法可以獲取到高等級的解析事件,并通過對比確定事件類型
while (parser.next() != XmlPullParser.END_DOCUMENT) {
//使用getName()方法獲得元素的名稱
String people = parser.getName();
String name = null;
String age = null;
String height = null;
if ((people != null) && people.equals("person")) {
//使用getAttributeCount()方法獲取元素的屬性數(shù)量
int count = parser.getAttributeCount();
for (int i = 0; i < count; i++) {
//通過getAttributeName()方法得到屬性名稱
String attrName = parser.getAttributeName(i);
String attrValue = parser.getAttributeValue(i);
//分析屬性名獲取到正確的屬性值
if ((attrName != null) && attrName.equals("name")){
name = attrValue;
} else if ((attrName != null) && attrName.equals("age")) {
age = attrValue;
} else if ((attrName != null) && attrName.equals("height")) {
height = attrValue;
}
}
//將屬性值整理成需要顯示的信息
if ((name != null) && (age != null) && (height != null)) {
msg+="姓名:"+name+",年齡:"+age+",身高:"+height+"\n";
}
}
}
} catch (Exception e) {
Log.e("ResourceFileDemo", e.getMessage(), e);
}
displayView.setText(msg);
這里介紹一下XmlPullParser的XML事件類型,如表7-3所示。
表7-3 XmlPullParser的XML事件類型
事件類型 |
說明 |
START_TAG |
讀取到標簽開始標志 |
TEXT |
讀取文本內容 |
END_TAG |
讀取到標簽結束標志 |
END_DOCUMENT |
文檔末尾 |