1. 程式人生 > >Android專案中的assets和raw

Android專案中的assets和raw

*res/raw和assets的相同點:

1.兩者目錄下的檔案在打包後會原封不動的儲存在apk包中,不會被編譯成二進位制。

*res/raw和assets的不同點:
1.res/raw中的檔案會被對映到R.Java檔案中,訪問的時候直接使用資源ID即R.id.filename;assets資料夾下的檔案不會被對映到R.java中,訪問的時候需要AssetManager類。
2.res/raw不可以有目錄結構,而assets則可以有目錄結構,也就是assets目錄下可以再建立資料夾

*讀取檔案資源:

1.讀取res/raw下的檔案資源,通過以下方式獲取輸入流來進行寫操作

· InputStream is =getResources().openRawResource(R.id.filename);

2.讀取assets下的檔案資源,通過以下方式獲取輸入流來進行寫操作

· AssetManager am = null;

· am = getAssets();

· InputStream is = am.open(“filename”);

注意1:Google的Android系統處理Assert有個bug,在AssertManager中不能處理單個超過1MB的檔案,不然會報異常,raw沒這個限制可以放個4MB的Mp3檔案沒問題。

注意2:assets 資料夾是存放不進行編譯加工的原生檔案,即該資料夾裡面的檔案不會像 xml, java 檔案被預編譯,可以存放一些圖片,html,js, css 等檔案。

本文例項講述了Android播放assets檔案裡視訊檔案相關問題。分享給大家供大家參考,具體如下:

今天做了一個功能,就是播放專案工程裡面的視訊檔案,不是播放SD卡視訊檔案。

我開始嘗試把視訊檔案放到 assets檔案目錄下。

因為之前寫webview載入assets資料夾時,是這樣寫的:

webView = new WebView(this); webView.loadUrl(file:///android_asset/sample3_8.html);
依次類推,我嘗試將視訊video.3gp 放到assets目錄下,然後寫了下面的程式碼:

Intent it = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse(name);
it.setDataAndType(uri ,”video/3gp);
startActivity(it);
啟動了Android系統播放器,提示了一些資訊(沒有記錄下來),大概意思就是無法播放這個路徑下面的檔案/無法找到這個路徑檔案。

google了一下,中文網頁上幾乎沒有解決辦法的說明,按照慣例,去 http://stackoverflow.com 搜尋答案,找到了這個帖子:

I want to play a video from my assets or raw folder in my app inANDROID

播放Android專案工程裡的視訊檔案最終解決辦法是:

  1. 把視訊檔案放到專案工程的 res/raw 檔案下。

2.視訊檔案必須是Android支援視訊格式(3gp,wmv,mp4),並且命名必須是小寫字母,資料,下劃線,例如:my_video_file.mp4

  1. 當你是在程式碼裡面引用這個資原始檔時,你必須使用Rstatics類,同時去掉檔案的字尾:R.raw.my_video_file

  2. 這個Activity class 應該有一個 helper 方法getPackageName(),這樣便於你在你的程式碼裡面構造正確的URI。

    VideoView vv = (VideoView)this.findViewById(R.id.videoView); String uri = “android.resource://” + getPackageName() + “/” + R.raw.my_video_file;
    vv.start();

第一種是res目錄下存放的可編譯的資原始檔:

這種資原始檔系統會在R.java裡面自動生成該資原始檔的ID,所以訪問這種資原始檔比較簡單,通過R.XXX.ID即可;

第二種是assets目錄下存放的原生資原始檔:

因為系統在編譯的時候不會編譯assets下的資原始檔,所以我們不能通過R.XXX.ID的方式訪問它們。那我麼能不能通過該資源的絕對路徑去訪問它們呢?因為apk安裝之後會放在/data/app/**.apk目錄下,以apk形式存在,asset/res和被繫結在apk裡,並不會解壓到/data/data/YourApp目錄下去,所以我們無法直接獲取到assets的絕對路徑,因為它們根本就沒有。

還好Android系統為我們提供了一個AssetManager工具類。

檢視官方API可知,AssetManager提供對應用程式的原始資原始檔進行訪問;這個類提供了一個低級別的API,它允許你以簡單的位元組流的形式開啟和讀取和應用程式繫結在一起的原始資原始檔。

AssetManager類

概述:

提供對應用程式的原始資原始檔進行訪問;這個類提供了一個低級別的API,它允許你以簡單的位元組流的形式開啟和讀取和應用程式繫結在一起的原始資原始檔。通過getAssets()方法獲取AssetManager物件。

AssetManager類常用方法:

Public Methods

final String[]

list(String path)

返回指定路徑下的所有檔案及目錄名。

final InputStream

open(String fileName)

使用 ACCESS_STREAMING模式開啟assets下的指定檔案。.

final InputStream

open(String fileName, int accessMode)

使用顯示的訪問模式開啟assets下的指定檔案.

應用例項

1.載入assets目錄下的網頁:

//載入assets/win8_Demo/目錄下的index.html網頁

webView.loadUrl(“file:///android_asset/win8_Demo/index.html”);

說明:這種方式可以載入assets目錄下的網頁,並且與網頁有關的css,js,圖片等檔案也會的載入

2.訪問assets目錄下的資原始檔:

AssetManager.open(String filename),返回的是一個InputSteam型別的位元組流,這裡的filename必須是檔案比如(aa.txt;img/semll.jpg),而不能是資料夾。

3.獲取assets的檔案及目錄名:

//獲取assets目錄下的所有檔案及目錄名,content(當前的上下文如Activity,Service等ContextWrapper的子類的都可以)

String fileNames[] =context.getAssets().list(path);

4.將assets下的檔案複製到SD卡:

/** 
 *  從assets目錄中複製整個資料夾內容 
 *  @param  context  Context 使用CopyFiles類的Activity
 *  @param  oldPath  String  原檔案路徑  如:/aa 
 *  @param  newPath  String  複製後路徑  如:xx:/bb/cc 
 */
public void copyFilesFassets(Context context,String oldPath,String newPath) {                    
         try {
        String fileNames[] = context.getAssets().list(oldPath);//獲取assets目錄下的所有檔案及目錄名
        if (fileNames.length > 0) {//如果是目錄
            File file = new File(newPath);
            file.mkdirs();//如果資料夾不存在,則遞迴
            for (String fileName : fileNames) {
               copyFilesFassets(context,oldPath + "/" + fileName,newPath+"/"+fileName);
            }
        } else {//如果是檔案
            InputStream is = context.getAssets().open(oldPath);
            FileOutputStream fos = new FileOutputStream(new File(newPath));
            byte[] buffer = new byte[1024];
            int byteCount=0;               
            while((byteCount=is.read(buffer))!=-1) {//迴圈從輸入流讀取 buffer位元組        
                fos.write(buffer, 0, byteCount);//將讀取的輸入流寫入到輸出流
            }
            fos.flush();//重新整理緩衝區
            is.close();
            fos.close();
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        //如果捕捉到錯誤則通知UI執行緒
                   MainActivity.handler.sendEmptyMessage(COPY_FALSE);
    }                           
}

這裡寫圖片描述
這裡寫圖片描述
5.使用assets目錄下的圖片資源:

InputStream is=getAssets().open("wpics/0ZR424L-0.jpg");
Bitmap bitmap=BitmapFactory.decodeStream(is);
imgShow.setImageBitmap(bitmap);

這裡寫圖片描述