亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android 原始資源文件的使用詳解

2020-04-11 12:21:27
字體:
來源:轉載
供稿:網友
背景知識介紹
與其他平臺的應用程序一樣,Android中的應用程序也會使用各種資源,比如圖片,字串等,會把它們放入源碼的相應文件夾下面,如/res/drawable, /res/xml, /res/values/, /res/raw, /res/layout和/assets。Android也支持并鼓勵開發者把UI相關的布局和元素,用XML資源來實現。總結起來,Android中支持的資源有:
•顏色值                 /res/values               以resources為Root的XML文件,定義形式為<color name>value</color>
•字串                    /res/values                以resources為Root的XML文件<string name>value</string>
•圖片                    /res/drawable            直接放入,支持9 Patch可自由拉伸
•圖片的顏色        /res/values               以resources為Root的XML文件,定義形式為<drawable name>value</drawable>
•單位資源            /res/values               以resources為Root的XML文件<dimen name>value</dimen>
•菜單                    /res/menu                以menuo為root的XML文件
•布局                    /res/layout                 這個就是GUI的布局和元素
•風格和主題        /res/values                以resources為Root的XML文件<style name>value</style>
•動畫                    /res/anim                 有二種:一個是幀動畫(frame animation),也就是連續變換圖片以animation-list為Root的XML文件;另外一種就是補間動畫(tweened animation),它對應于API中的Animation和AnimationSet,有translate、scale、rotate、alpha四種,以set為root來定義,這個set就相當于AnimationSet
再說下目錄:
•/res/anim                  用于存放動畫
•/res/drawable          存放圖片,或等同于圖片的資源如shape,或selector
•/res/menu                 存放Menu
•/res/values               存放修飾性資源:字串,顏色,單位,風格和主題
•/res/layout                存放UI布局和元素
•/res/raw                    存放運行時想使用的原始文件
•/assets                     存放運行時想使用的原始文件
除了原始文件目錄/res/raw和/assets以外,其他的資源在編譯的時候都會被第三方軟件aapt進行處理,一個是把圖片和XML文件進行處理,例如把XML編譯成為二進制形式;另外處理的目的就是生成R.java文件,這個文件是訪問資源時必須要用到的。
/res目錄下面的所有文件都會映射到R.java文件中,以整數Id的形式被標識,相同類型的資源被一個內部類來封裝,一個R.java的文件類似于這樣:
復制代碼 代碼如下:

/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */
package com.android.explorer;
public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class id {
        public static final int action=0x7f060004;
        public static final int description_panel=0x7f060001;
        public static final int fileinfo=0x7f060003;
        public static final int filename=0x7f060002;
        public static final int linearlayout_test_1=0x7f060005;
        public static final int linearlayout_test_2=0x7f060006;
        public static final int linearlayout_test_3=0x7f060007;
        public static final int thumbnail=0x7f060000;
    }
    public static final class layout {
        public static final int fileant_list_item=0x7f030000;
        public static final int linearlayout_test=0x7f030001;
    }
    public static final class raw {
        public static final int androidmanifest=0x7f040000;
    }
    public static final class string {
        public static final int app_name=0x7f050001;
        public static final int hello=0x7f050000;
    }
}

從這個R.java就可看出在/res中定義或提供資源時的注意事項:
1. 同一個類型,或同一文件夾下面的資源不可以使用相同的文件名,也就是說不能用文件擴展名來區別不同的文件,因為R.java中只保留資源的文件名而不管擴展名,所以如果有二個圖片一個是icon.png另一個是icon.jpg,那么在R.java中只會有一個R.drawable.icon。另外一個則會無法訪問到。
2. 資源文件的名字必須符合Java變量的命名規則,且不能有大寫,只能是'[a-z][0-9]._',否則會有編譯錯誤,因為R.java中的變量Id要與資源中的文件一一對應,也就是說用資源文件名來作為Id的變量名,所以一定要符合Java變量的命名規則,另外它還不能有大寫。
3. 除了SDK支持的folder外,不能再有子Folder,雖不會有編譯錯誤,但是子Folder會被完全忽略,如在/res/layout下在建一個子Folder activity(/res/layout/acitivity/, 那么你在生成的R.java中是看不到activity和其內的內容的。
4. 對于資源文件的大小有限制,最好不要讓單個文件大于1M,這是SDK文檔說明的限制,但具體的我沒有進行試驗(據說2.2版本以后的可支持到10M,不知道是真的還是假的)
5. 所有/res下面的資源都能通過Resources()并提供Id來訪問。
使用原始資源
對于大多數資源在編譯時會對文件內容進行特殊處理,以方便Apk在運行時訪問。 如果想要運行時使用未經處理的原始資源,可以把資源文件放在/res/raw和/assets目錄下面,這二個目錄的主要區別在于:
1. /res/raw中的文件會被映射到R.java中
雖然/res/raw中的文件不會被aapt處理成為二進制,但是它的文件還是被映射到R.java中,以方便以資源Id形式來訪問
2. 子目錄結構
如上面所述,/res/raw中雖可以有子目錄,但是在程序運行時是無法訪問到的,因為/res下面的所有非法子目錄在R.java中都是看不到的。而且這些子目錄和文件都不會被編譯進入Apk中,解壓Apk文件后也看不到/res/raw下面去找了。
而/assets是允許有子目錄的,并且完全可以訪問到,并且會被打包進Apk,解壓Apk后,這些文件仍然存在并且與源碼包中的一樣。
3. 訪問方式
/res/raw下面的文件(子文件夾是訪問不到的了)的訪問方式是通過Resources,并且必須提供資源的Id
復制代碼 代碼如下:

InputStream in = Context.getResources().openRawResource(R.id.filename);

所以為什么子文件夾無法訪問,因為沒有Id啊。
而/assets則要通過AssetManager來訪問。下面著重講解如何訪問/assets下面的資源文件。
通過AssetManager來訪問/assets下面的原始資源文件
1. 文件的讀取方式
用AssetManager.open(String filename)來打開一個文件,這是一組重載方法,還有其他參數可以設置打開模式等,可以參考文檔
這里的filename是相對于/assets的路徑,比如:
復制代碼 代碼如下:

InputStream in = mAssetManager.open("hello.txt"); // '/assets/hello.txt'
InputStream in2 = mAssetManager.open("config/ui.txt"); // '/assets/config/ui.txt'

2. 文件夾處理 --- 如何遍歷/assets
可以看到如果想要訪問/assets下面的文件,必須要知道文件名和相對于/assets的路徑。所以,如果你不預先知道其下面有什么的時候又該如何處理呢?那就需要列出它下面所有的文件,然后再選取我們需要的,所以新的問題來了,如何列出/assets下面所有的文件呢?
AssetManager提供了一個列出/assets下某個路徑下面的方法:
復制代碼 代碼如下:

public finalString[]list(String path)
Since: API Level 1
Return a String array of all the assets at the given path.
Parameters
path  A relative path within the assets, i.e., "docs/home.html".
Returns
•String[] Array of strings, one for each asset. These file names are relative to 'path'. You can open the file by concatenating 'path' and a name in the returned string (via File) and passing that to open().

其實這個文檔寫的有問題,list()是列出一個文件夾下面的文件,所以應該傳入一個文件夾路徑而非文檔中的"docs/home.html"。
還有一個最大的問題就是如何列出根目錄/assets下面的內容,因為只有知道了根目錄下面的東西,才能去相對的子目錄去找東西,所以這是個必須最先解決的問題。
其實文檔沒有說的太明白這個方法到底如何使用,也就是說這個String參數到底如何傳。猜想著根目錄為/assets,所以嘗試了以下:
復制代碼 代碼如下:

mAssetManager.list(".");  // returns array size is 0
mAssetManager.list("/");  // returns [AndroidManifest.xml, META-INF, assets, classes.dex, res, resources.arsc] // don't worry, u can see these files though, no way to access them
mAssetManager.list("/assets");  // returns array size is 0
//Google了一下,找到了正解:
mAssetManager.list("");  // returns stuff in /assets

然后再根據所列出的子項去遞歸遍歷子文件,直到找到所有的文件為止。
常見的問題
1. 資源文件只能以InputStream方式來獲取
如果想操作文件怎么辦,如果想要用文件Uri怎么辦。光靠API當然不行,它只給你InputStream,也就是說它是只讀的??尚械霓k法就是讀取文件然后寫入一個臨時文件中,再對臨時文件進行想要的文件操作??梢栽趦炔看鎯蛲獠看鎯ι厦嬗肅ontext提供的接口來創建文件,詳細的請參考<Android開發筆記之: 數據存儲方式詳解>。Java牛人可能想要用Java本身的能力:
復制代碼 代碼如下:

File File.createTempFile(String prefix, String suffix); 
File File.createTempFile(String prefix, String suffix, File path); 

這也是可以的,但要考慮Android系統的特性,也就是說所寫的路徑是否有權限。比如對于第一個方法,用的是"java.io.tmpdir"這個在Android當中就是"/sdcard",所以當沒有SD卡時這個方法必拋異常。
2. 所有資源文件都是只讀的,運行時無法更改
因為,程序運行時是把Apk動態解析加載到內存中,也就是說,Apk是不會有變化的,它是無法被改變的。
3. 所有的資源文件夾/res和/assets也都是只讀的,不可寫入
如上面所說,Apk是在編譯后是無法再改變的了。
實例
下面是一個實例,可以遞歸式的遍歷/assets下面所有的文件夾和文件
復制代碼 代碼如下:

package com.android.explorer;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.MimeTypeMap;
import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
/*
 * Explore all stuff in /assets and perform actions specified by users.
 */
public class FileAntActivity extends ListActivity {
    private static final String TAG = "FileAntActivity";
    private AssetManager mAssetManager;
    private static final String EXTRA_CURRENT_DIRECTORY = "current_directory";
    private static final String EXTRA_PARENT = "parent_directory";
    public static final String FILEANT_VIEW = "com.android.fileant.VIEW";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = getIntent();
        String current = null;
        String parent = null;
        if (intent != null && intent.hasExtra(EXTRA_CURRENT_DIRECTORY)) {
            current = intent.getStringExtra(EXTRA_CURRENT_DIRECTORY);
        }
        if (current == null) {
            current = "";
        }
        if (intent != null && intent.hasExtra(EXTRA_PARENT)) {
            parent = intent.getStringExtra(EXTRA_PARENT);
        }
        if (parent == null) {
            parent = "";
        }
        mAssetManager = getAssets();
        if (TextUtils.isEmpty(parent)) {
            setTitle("/assets");
        } else {
            setTitle(parent);
        }
        try {
            // List all the stuff in /assets
            if (!TextUtils.isEmpty(parent)) {
                current = parent + File.separator + current;
            }
            Log.e(TAG, "current: '" + current + "'");
            String[] stuff = mAssetManager.list(current);
            setListAdapter(new FileAntAdapter(this, stuff, current));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private class FileAntAdapter extends BaseAdapter {
        private Context mContext;
        private String[] mEntries;
        private String mParentDirectory;

        public FileAntAdapter(Context context, String[] data, String parent) {
            mContext = context;
            this.mEntries = data;
            mParentDirectory = parent;
        }

        public int getCount() {
            return mEntries.length;
        }
        public Object getItem(int position) {
            return mEntries[position];
        }
        public long getItemId(int position) {
            return (long) position;
        }
        public View getView(final int position, View item, ViewGroup parent) {
            LayoutInflater factory = LayoutInflater.from(mContext);
            if (item == null) {
                item = factory.inflate(R.layout.fileant_list_item, null);
                TextView filename = (TextView) item.findViewById(R.id.filename);
                TextView fileinfo = (TextView) item.findViewById(R.id.fileinfo);
                ImageButton action = (ImageButton) item.findViewById(R.id.action);
                final String entry = mEntries[position];
                filename.setText(entry);
                boolean isDir = isDirectory(entry);
                if (isDir) {
                    fileinfo.setText("Click to view folder");
                    action.setVisibility(View.GONE);
                    item.setClickable(true);
                    item.setOnClickListener(new View.OnClickListener() {
                        public void onClick(View view) {
                            Intent intent = new Intent(FILEANT_VIEW);
                            intent.putExtra(EXTRA_CURRENT_DIRECTORY, entry);
                            intent.putExtra(EXTRA_PARENT, mParentDirectory);
                            startActivity(intent);
                        }
                    });
                } else {
                    final String type =
                        MimeTypeMap.getSingleton().getMimeTypeFromExtension(getExtension(entry));
                    fileinfo.setText(type);
                    item.setClickable(false);
                    action.setOnClickListener(new View.OnClickListener() {
                        public void onClick(View view) {
                             String filepath = entry;
                             if (!TextUtils.isEmpty(mParentDirectory)) {
                                 filepath = mParentDirectory + File.separator + filepath;
                             }
                             BufferedInputStream in = new BufferedInputStream(mManager.open(filepath));
                             // Do whatever you like with this input stream
                        }
                    });
                }
            }
            return item;
        }
     }

    /**
     * Test Whether an entry is a file or directory based on the rule:
     * File: has extension *.*, or starts with ".", which is a hidden files in Unix/Linux,
     * otherwise, it is a directory
     * @param filename
     * @return
     */
    private boolean isDirectory(String filename) {
        return !(filename.startsWith(".") || (filename.lastIndexOf(".") != -1));
    }

    private String getExtension(String filename) {
        int index = filename.lastIndexOf(".");
        if (index == -1) {
            return "";
        }
        return filename.substring(index + 1, filename.length()).toLowerCase();
    }
}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美成年人在线观看| 国产成+人+综合+亚洲欧洲| 欧美黑人一区二区三区| 精品免费在线观看| xvideos亚洲人网站| 国产美女久久久| 欧美性生交xxxxx久久久| 日韩美女av在线免费观看| 久久久噜噜噜久久久| 久久99热这里只有精品国产| 欧美国产日韩xxxxx| 97在线免费观看视频| 视频在线观看一区二区| 91亚洲va在线va天堂va国| 亚洲欧美另类自拍| 国产精品日韩在线一区| 日韩欧美在线观看| 久久精品国产精品亚洲| 草民午夜欧美限制a级福利片| 2018国产精品视频| 日韩av综合网| 色婷婷av一区二区三区久久| 欧美成人午夜免费视在线看片| 国产精品爽黄69| 亚洲精品久久久久久久久久久| 尤物yw午夜国产精品视频| 美女性感视频久久久| 欧美高清视频免费观看| 亚洲国产精久久久久久久| 国产精品美女主播| 欧美另类在线播放| 国产精品观看在线亚洲人成网| 国产在线999| 国产精品久久久久av免费| 亚洲一区二区三区毛片| 国产剧情久久久久久| 国产欧美一区二区三区视频| 国产日韩在线一区| 国产精品日韩在线观看| 91精品啪aⅴ在线观看国产| 日韩亚洲成人av在线| 欧美日韩一二三四五区| 欧美大胆在线视频| 91久久精品国产91久久| 国产欧美在线播放| 欧美性资源免费| 91在线色戒在线| 97超级碰碰人国产在线观看| 91手机视频在线观看| 91影院在线免费观看视频| 欧美精品制服第一页| 亚洲第一国产精品| 日本精品免费观看| 亚洲天堂av在线播放| 欧美性20hd另类| 久久综合久久88| 欧美日韩在线另类| 亚洲精品午夜精品| 午夜精品久久久久久99热软件| 亚洲摸下面视频| 国产精品综合久久久| 韩国三级电影久久久久久| 91美女片黄在线观| 在线观看欧美日韩国产| 久久久久这里只有精品| 国产精品视频导航| 亚洲成人免费在线视频| 中文字幕精品—区二区| 亚洲精品福利视频| 欧美国产一区二区三区| 日韩经典中文字幕在线观看| 日韩在线资源网| 色婷婷综合成人| 欧美电影在线观看高清| 亚洲自拍另类欧美丝袜| 国产精品青青在线观看爽香蕉| 日本一区二区不卡| 中文字幕亚洲二区| 亚洲аv电影天堂网| 91精品久久久久久| 久久精品亚洲精品| 国产主播喷水一区二区| 日韩av网站大全| 亚洲免费高清视频| 日韩欧美在线视频| 国产成人涩涩涩视频在线观看| 爽爽爽爽爽爽爽成人免费观看| 欧美精品一本久久男人的天堂| 欧美日韩加勒比精品一区| 亚洲第一精品自拍| 97人人模人人爽人人喊中文字| 国产综合视频在线观看| 亚洲曰本av电影| 国产主播精品在线| 亚洲第一男人天堂| 久久天堂av综合合色| 亚洲欧美一区二区精品久久久| 日韩在线观看高清| 国产原创欧美精品| 欧美极品在线播放| 97久久超碰福利国产精品…| 欧美大奶子在线| 最新69国产成人精品视频免费| 中文国产亚洲喷潮| 国产99久久久欧美黑人| 国产精品久久久久久久久久| 欧美激情一区二区三区在线视频观看| 亚洲成人在线视频播放| 亚洲天堂免费观看| 亚洲网站在线播放| 伦伦影院午夜日韩欧美限制| 欧美巨大黑人极品精男| 欧美性色xo影院| 精品美女永久免费视频| 欧美激情小视频| 日本高清久久天堂| 亚洲jizzjizz日本少妇| 欧美成人精品在线播放| 亚洲香蕉成人av网站在线观看| 欧美黑人巨大精品一区二区| 欧美日韩国产麻豆| 热久久免费视频精品| 欧美一区二区三区图| 奇门遁甲1982国语版免费观看高清| 青青草99啪国产免费| 久久久爽爽爽美女图片| 久久天天躁狠狠躁夜夜av| 另类专区欧美制服同性| 成人中文字幕+乱码+中文字幕| 久久久久久成人精品| 懂色av一区二区三区| 欧美激情精品久久久久久久变态| 成人欧美一区二区三区黑人| 精品一区电影国产| 日本精品视频在线观看| 96精品久久久久中文字幕| 国产69精品99久久久久久宅男| 国产精品久久久久久久久久久不卡| 欧美日韩在线视频观看| 日产日韩在线亚洲欧美| 久久免费国产视频| 久久久www成人免费精品| 欧美疯狂做受xxxx高潮| 久久久久久久一区二区| 欧美极品少妇xxxxⅹ免费视频| 色综合视频一区中文字幕| 成人午夜在线视频一区| 成人免费在线视频网址| 欧美有码在线视频| 中文字幕亚洲一区二区三区| 国产香蕉97碰碰久久人人| 92国产精品久久久久首页| 一个色综合导航| 黄色成人在线播放| 51午夜精品视频| 欧美猛交免费看| 91久久久久久久一区二区| 国产成人精品一区二区三区| 欧美国产日韩视频| 日本不卡视频在线播放| 国产亚洲xxx| 亚洲第一区在线观看| 亚洲精品日韩久久久| 久久久久国产视频|