首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 將 res/raw 資源檔案複製到 SD 卡的正確做法與權限設定

     編輯:程式設計綜合問答

問題背景

在 Android 開發中,有時需要將打包在 APK 內的原始資源(如 res/raw 目錄下的音訊檔案)複製到外部儲存裝置(SD 卡),以便其他應用或系統媒體掃描器能夠識別。許多開發者嘗試使用 FileOutputStream 直接寫入,卻發現檔案並未實際生成,且程式碼執行過程中沒有拋出明顯異常。

常見錯誤分析

以下代碼片段展示了典型的嘗試:

InputStream fIn = getResources().openRawResource(R.raw.song);
byte[] buffer = new byte[fIn.available()];
fIn.read(buffer);
fIn.close();

String path = "/sdcard/media/audio/ringtones/";
File dir = new File(path);
if (!dir.exists()) dir.mkdirs();

FileOutputStream save = new FileOutputStream(path + "examplefile.ogg");
save.write(buffer);
save.flush();
save.close();

sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
        Uri.parse("file://" + path + "examplefile.ogg")));

雖然邏輯看似正確,但忽略了兩個關鍵點:

  1. 缺少寫入外部儲存權限:Android 6.0 (API 23) 以上需要動態申請 WRITE_EXTERNAL_STORAGE,舊版本則需在 Manifest 中聲明。
  2. 硬編碼路徑不可靠:應使用 Environment.getExternalStorageDirectory() 獲取根目錄,而非固定 /sdcard/。

解決方案

1. 在 AndroidManifest.xml 添加權限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

針對 Android 10 (API 29) 以上,建議改用 MediaStore API 或應用專屬目錄(getExternalFilesDir()),無需權限即可讀寫。

2. 使用標準路徑與異步處理

// 在子執行緒執行 IO 操作
new Thread(() -> {
    try (InputStream in = getResources().openRawResource(R.raw.song);
         FileOutputStream out = new FileOutputStream(new File(
                 getExternalFilesDir(Environment.DIRECTORY_RINGTONES), "song.ogg"))) {
        byte[] buf = new byte[4096];
        int len;
        while ((len = in.read(buf)) > 0) out.write(buf, 0, len);
        // 通知媒體掃描
        MediaScannerConnection.scanFile(this,
                new String[]{out.getFile().getAbsolutePath()}, null, null);
    } catch (IOException e) {
        e.printStackTrace();
    }
}).start();

最佳實踐總結

  • 優先使用 getExternalFilesDir() 或 MediaStore,避免權限問題。
  • 檔案 IO 操作必須在背景執行緒,防止 ANR。
  • 寫入後主動呼叫 MediaScannerConnection.scanFile() 更新媒體庫。
  • 針對 Android 10+ 遵循分區儲存規範,勿直接訪問公開目錄。

採用上述方法,即可可靠地將原始資源導出為獨立媒體檔案,供系統鈴聲選擇器或其他應用使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved