天天看點

Android 資源檔案分布

A pk 檔案下的資源檔案都存放在以下兩個目錄下: res/ , assets/ , res/ 目錄下的檔案在打包成 apk 的時候被 encode 過,文本檔案也變成了二進制的。如果想看文本内容,請參考下 android-apktool 工程。assets/ 目錄下的檔案會被原封不動的打包到 apk 檔案中去。下面以一個例子說明下。

    資源源檔案目錄結構如下:

Xml代碼  

[lgao@lgao -]$ tree  

.  

|-- AndroidManifest.xml  

|-- assets  

|   |-- default.properties  

|   |-- docs  

|   |   `-- test.file  

|   `-- test.xml  

|-- res  

|   |-- drawable  

|   |   |-- taobao.ico  

|   |   `-- taobao_tabs.xml  

|   |-- drawable-hdpi  

|   |   `-- icon.png  

|   |-- drawable-ldpi  

|   |-- drawable-mdpi  

|   |-- layout  

|   |   |-- main.xml  

|   `-- values  

|       `-- strings.xml  

    當 apk 安裝到模拟器中後, apk 被安裝在 /data/app/test.apk ,我們來測試下檔案内容:

Java代碼  

try {  

ZipInputStream zipIn = new ZipInputStream(new FileInputStream("/data/app/test.apk"));  

BufferedReader zipReader = new BufferedReader(new InputStreamReader(zipIn));  

ZipEntry entry = null;  

while((entry = zipIn.getNextEntry()) != null)  

{  

    Log.i("TEST[APK-ENTRY]", entry.getName());  

    if(entry.getName().indexOf("assets") != -1){  

        String sl = null;  

        while((sl = zipReader.readLine()) != null){  

            Log.i("TEST[xml reader assets]", sl);  

        }  

    }else if (entry.getName().endsWith(".xml")){  

            Log.i("TEST[xml reader xml]", sl);  

    }  

}  

} catch (FileNotFoundException e) {  

    // TODO Auto-generated catch block  

} catch (IOException e) {  

    e.printStackTrace();  

  我們看得到的 Logcat 消息:

12-12 13:43:28.234: INFO/TEST[APK-ENTRY](740): assets/docs/test.file  

12-12 13:43:28.254: INFO/TEST[xml reader assets](740): # test string line  

12-12 13:43:28.295: INFO/TEST[APK-ENTRY](740): assets/default.properties  

12-12 13:43:28.314: INFO/TEST[xml reader assets](740): # This file is automatically generated by Android Tools.  

12-12 13:43:28.354: INFO/TEST[APK-ENTRY](740): assets/test.xml  

12-12 13:43:28.364: INFO/TEST[xml reader assets](740): <? xml encoding="utf-8" ?>  

12-12 13:43:28.364: INFO/TEST[xml reader assets](740): <product>  

12-12 13:43:28.364: INFO/TEST[xml reader assets](740): Test Name  

12-12 13:43:28.384: INFO/TEST[xml reader assets](740): </product>  

12-12 14:47:02.745: INFO/TEST[APK-ENTRY](740): res/drawable/taobao.ico  

12-12 14:47:02.775: INFO/TEST[APK-ENTRY](740): res/drawable/taobao_tabs.xml  

12-12 14:47:02.795: INFO/TEST[xml reader xml](740): 4  

12-12 14:47:02.795: INFO/TEST[APK-ENTRY](740): res/layout/main.xml  

12-12 14:47:02.815: INFO/TEST[xml reader xml](740): L  

12-12 14:47:02.925: INFO/TEST[APK-ENTRY](740): AndroidManifest.xml  

12-12 14:47:02.956: INFO/TEST[xml reader xml](740):   

12-12 14:47:03.185: INFO/TEST[APK-ENTRY](740): resources.arsc  

12-12 14:47:03.265: INFO/TEST[APK-ENTRY](740): res/drawable-hdpi/icon.png  

12-12 14:47:03.285: INFO/TEST[APK-ENTRY](740): res/drawable-ldpi/icon.png  

12-12 14:47:03.304: INFO/TEST[APK-ENTRY](740): res/drawable-mdpi/icon.png  

12-12 14:47:03.324: INFO/TEST[APK-ENTRY](740): classes.dex  

12-12 14:47:03.374: INFO/TEST[APK-ENTRY](740): META-INF/MANIFEST.MF  

12-12 14:47:03.394: INFO/TEST[APK-ENTRY](740): META-INF/CERT.SF  

12-12 14:47:03.404: INFO/TEST[APK-ENTRY](740): META-INF/CERT.RSA  

    從 LogCat 消息我們看到, 所有在 assets/ 目錄下的檔案都以原始檔案格式存放, 是以我們能正确的顯示它的内容, 但是在 res/ 目錄下的檔案,即便是 xml 的文本檔案, 也隻能顯示出為亂碼。當然在 Android app 下讀取 assets/ 目錄下檔案不能使用這種方式, 而是 Android 提供的 AssetManager 來實作。

    Activity 下提供了許多擷取一個 File 的方法, 我們需要知道這些 File 具體指向 Android 的哪個位置。 我們也來測試一下:

Log.i("TEST[getCacheDir()]", getCacheDir().getAbsolutePath());  

Log.i("TEST[getDatabasePath()]", getDatabasePath("test.db").getAbsolutePath());  

Log.i("TEST[getDir()]", getDir("testDir", Context.MODE_PRIVATE).getAbsolutePath());  

Log.i("TEST[getExternalCacheDir()]", getExternalCacheDir().getAbsolutePath());  

Log.i("TEST[getExternalFilesDir('')]", getExternalFilesDir("").getAbsolutePath());  

Log.i("TEST[getExternalFilesDir('test_data')]", getExternalFilesDir("test_data").getAbsolutePath());  

Log.i("TEST[getExternalFilesDir('music')]", getExternalFilesDir("music").getAbsolutePath());  

Log.i("TEST[getFilesDir()]", getFilesDir().getAbsolutePath());  

Log.i("TEST[getFileStreamPath('test_steam.file')]", getFileStreamPath("test_steam.file").getAbsolutePath());  

     我們看下 LogCat 結果:

12-12 15:06:25.715: INFO/TEST[getCacheDir()](1702): /data/data/org.tangao.pettyman/cache  

12-12 15:06:25.745: INFO/TEST[getDatabasePath()](1702): /data/data/org.tangao.pettyman/databases/test.db  

12-12 15:06:25.755: INFO/TEST[getDir()](1702): /data/data/org.tangao.pettyman/app_testDir  

12-12 15:06:25.965: INFO/TEST[getExternalCacheDir()](1702): /mnt/sdcard/Android/data/org.tangao.pettyman/cache  

12-12 15:06:26.174: INFO/TEST[getExternalFilesDir('')](1702): /mnt/sdcard/Android/data/org.tangao.pettyman/files  

12-12 15:06:26.250: INFO/TEST[getExternalFilesDir('test_data')](1702): /mnt/sdcard/Android/data/org.tangao.pettyman/files/test_data  

12-12 15:06:26.367: INFO/TEST[getExternalFilesDir('music')](1702): /mnt/sdcard/Android/data/org.tangao.pettyman/files/music  

12-12 15:06:26.384: INFO/TEST[getFilesDir()](1702): /data/data/org.tangao.pettyman/files  

12-12 15:06:26.424: INFO/TEST[getFileStreamPath('test_steam.file')](1702): /data/data/org.tangao.pettyman/files/test_steam.file  

    除了以上的資源檔案外, Android 還有 database 檔案的支援, 而 database 檔案是在相應 SQLiteOpenHelper 實作的 getReadableDatabase() 或者 getWritableDatabase() 方法在第一次被調用的時候建立的,然後調用 SQLiteOpenHelper 的 onCreate(SQLiteDatabase db) 方法, 如果 Database 的版本有變化, 不管是版本号變高還是變低都會調用 onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 方法。