1. 程式人生 > >Android res/raw 和 assets 使用

Android res/raw 和 assets 使用

今天在研究通知欄的時候,不想用系統預設的提示音,就想著自定義提示音,瞭解到可以可以在專案中新增raw資料夾或者assets資料夾來存放音訊,使用raw的話是放在res下面的,也就是說可以直接用過R.raw.xxx.mp3,獲取到該音訊。
注意:但是該資料夾下的音訊會被編譯成二進位制檔案,不能直接開啟

音訊

具體的新建方法:

新建raw

下面是程式碼,說明下,我是為了圖方便直接在BroadcastReceiver的onReceive方法裡面傳送Notification的,最好不要在onReceive方法裡面做耗時操作。

public class Receiver1 extends BroadcastReceiver
{
NotificationManager manager; int notificationId = 0; @Override public void onReceive(Context context, Intent intent) { Intent intent1 = new Intent(context,MainActivity.class);//啟動Activity的Intent PendingIntent pintent = PendingIntent.getActivity(context,0,intent1,0); Notification.Builder builder = new
Notification.Builder(context); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setTicker("Hello");//手機狀態列的提示 builder.setWhen(System.currentTimeMillis());//設定時間 builder.setContentTitle("通知欄通知"); builder.setContentText("練習Notification"); builder.setContentIntent(pintent);//點選之後的意圖
builder.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/"+R.raw.sound));//自定義聲音 // builder.setDefaults(Notification.DEFAULT_SOUND);//設定聲音 builder.setDefaults(Notification.DEFAULT_LIGHTS);//設定指示燈,,,,,指示燈個震動都需要配置許可權 builder.setDefaults(Notification.DEFAULT_VIBRATE);//設定震動效果 // builder.setDefaults(Notification.DEFAULT_ALL);//設定上面的三種效果 //Android4.1以上的版本用Notification notification = builder.build(); //Android4.1以下的版本用builder.getNotification(); manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = builder.build(); manager.notify(notificationId,notification); } }

檔案

在如下位置新建 assets 資料夾:

Paste_Image.png

然後裡面用到了一個 error.html 的 html 檔案,用於在載入 webView 失敗的時候展示給使用者。

使用:

webView.loadUrl("file:///android_asset/error.html");

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

這樣就可以使用了,是不是很簡單呢?

後續

相同點

兩者目錄下的檔案在打包後會原封不動的儲存在apk包中,不會被編譯成二進位制,這些檔案將被打包到APK中應用使用。

不同點

區別 一

可能有的朋友會問了,既然兩種方式都是不會被編譯成二進位制檔案,而我們在引用音訊檔案的時候,使用的是 R.raw.xxx.mp3 這種方式,為什麼在使用檔案的時候要使用 webView.loadUrl("file:///android_asset/error.html"); 這種方式?難道不能也使用 R.assets.errpr.html 這種方式來引用檔案嗎?

要弄清這個問題,首先要明白第一個不同點:

  • res/raw 中的檔案會被對映到 R.java 檔案中,訪問的時候直接使用資源 ID 即 R.raw.xxx.mp3;
  • assets 資料夾下的檔案不會被對映到 R.java 中,訪問的時候需要 AssetManager 類。

那麼我們既然不能通過使用 R 檔案的方式引用,我們可以通過使用絕對路徑的方式去引用嗎?

答案是否定的!

因為 apk 檔案安裝之後會放在 /data/app/ 目錄下,以 apk 形式存在, asset/res 被繫結在 apk 裡,並不會解壓到 /data/data/你的應用包名 目錄下去,所以我們無法直接獲取到 assets 的絕對路徑,因為它們根本就沒有。

注意:下面的只能在已經 Root 的手機或者模擬器中可以看到

首先我們看下我們的手機在沒安裝 app 的情況下,data/app 資料夾下面有什麼檔案?

Paste_Image.png

現在我們來安裝一下簡書 App :

Paste_Image.png

我們發現,我們安裝的 app 確實是出現在了 /data/app 資料夾下面。

這個時候如果你點開 /data/data/你的應用包名 資料夾檢視的話,是看不到 assets 資料夾的,說明並沒有解壓到這裡,所以就不能使用絕對路徑去引用了。

  • system/app 系統自帶的應用程式,無法刪除。
  • data/app 使用者程式安裝的目錄,有刪除許可權。安裝時把apk檔案複製到此目錄。
  • data/data 存放應用程式的資料。
  • data/dalvik-cache 將 apk 中的 dex 檔案安裝到 dalvik-cache 目錄下( dex 檔案是 dalvik 虛擬機器的可執行檔案,其大小約為原始 apk 檔案大小的四分之一)。

APP安裝過程:複製APK安裝包到data/app目錄下,解壓並掃描安裝包,把dex檔案(Dalvik位元組碼)儲存到dalvik-cache目錄,並data/data目錄下建立對應的應用資料目錄。

附錄:

  1. res/anim/ XML檔案,它們被編譯進逐幀動畫(frame by frame animation)或補間動畫(tweened animation)物件
  2. res/drawable/

    • .png、.9.png、.jpg檔案,它們被編譯進以下的Drawable資源子型別中:
    • 要獲得這種型別的一個資源,可以使用Resource.getDrawable(id)
    • 點陣圖檔案
    • 9-patches(可變尺寸的點陣圖)
    • 為了獲取資源型別,使用mContext.getResources().getDrawable(R.drawable.imageId)
      注意:放在這裡的影象資源可能會被aapt工具自動地進行無失真壓縮優化。比如,一個真彩色但並不需要256色的PNG可能會被轉換為一個帶調色盤的8位PNG。這使得同等質量的圖片佔用更少的資源。所以我們得意識到這些放在該目錄下的二進位制影象在生成時可能會發生變化。如果你想讀取一個影象位流並轉換成一個位圖(bitmap),請把影象檔案放在res/raw/目錄下,這樣可以避免被自動優化。
  3. res/layout/ 被編譯為屏幕布局(或螢幕的一部分)的XML檔案。參見佈局宣告(Declaring Layout)

  4. res/values/
    • 可以被編譯成很多種型別的資源的XML檔案。注意: 不像其他的res/資料夾,它可以儲存任意數量的檔案,這些檔案儲存了要建立資源的描述,而不是資源本身。XML元素型別控制這些資源應該放在R類的什麼地方,儘管這個資料夾裡的檔案可以任意命名,不過下面使一些比較典型的檔案(檔案命名的慣例是將元素型別包含在該名稱之中):
    • array.xml 定義陣列
    • colors.xml 定義color drawable和顏色的字串值(color string values)。使用Resource.getDrawable()和Resources.getColor()分別獲得這些資源。
    • dimens.xml定義尺寸值(dimension value)。使用Resources.getDimension()獲得這些資源。
    • strings.xml定義字串(string)值。使用Resources.getString()或者Resources.getText()獲取這些資源。getText()會保留在UI字串上應用的豐富的文字樣式。
    • styles.xml 定義樣式(style)物件。
  5. res/xml/ 任意的XML檔案,在執行時可以通過呼叫Resources.getXML()讀取。
  6. res/raw/ 直接複製到裝置中的任意檔案。它們無需編譯,新增到你的應用程式編譯產生的壓縮檔案中。要使用這些資源,可以呼叫Resources.openRawResource(),引數是資源的ID,即R.raw.somefilename。

區別 二

另外需要我們注意的是:

  • res/raw 不可以有目錄結構,也就是說只能存放一級目錄,不能再下面建立資料夾。
  • 而 assets 則可以有目錄結構,也就是 assets 目錄下可以再建立任意深度和數量的資料夾

assets 下面檔案的使用

html檔案

如上面例子所示

其他檔案

獲取 AssetManager

    AssetManager assetManager =getAssets();
    InputStream is = assetManager.open("filename");  

補充一下:在未知目錄下有哪些檔案,該去和獲取這些檔案的名稱並把檔案拷貝到目標目錄中呢?(用於內建檔案但不知道檔名稱,需要篩選出想要的檔案然後拷貝到目標目錄中,推薦內建在assets資料夾中)
1. res/raw目錄:
通過反射的方式得到R.java裡面raw內部類裡面所有的資源ID的名稱,然後通過名稱獲取資源ID的值來讀取我們想要的檔案。(這個方法我沒試過,有用過的同學麻煩發一段程式碼看看)。
2. assets目錄:
getAssets().list(“”);來獲取assets目錄下所有資料夾和檔案的名稱,再通過這些名稱再讀取我們想要的檔案。