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

Android 應對不同機型存儲路徑差異的最佳實踐

     編輯:程式設計綜合問答

Android 設備存儲路徑差異巨大:有無 SD 卡、內部存儲劃分方式、可移動存儲掛載點等。正確獲取可用存儲目錄應使用系統 API 而非硬編碼路徑。

核心 API 方法

1. 獲取應用專屬外部存儲目錄 (推薦,無需權限)


// 返回: /storage/emulated/0/Android/data/com.example.app/files/
// 或: /storage/sdcard1/Android/data/com.example.app/files/ (次級外部存儲)
File appExternalDir = context.getExternalFilesDir(null); // 根目錄
File appExternalPicsDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); // 圖片子目錄
// 卸載應用時自動刪除,無需權限 (API 19+)

2. 獲取公共外部存儲目錄 (需權限,媒體文件適用)


// 返回: /storage/emulated/0/Pictures/ 等
File publicPicsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
// 需 READ/WRITE_EXTERNAL_STORAGE 權限 (API 29 以下)

3. 獲取所有外部存儲卷 (多存儲設備)


// API 19+ (KitKat)
File[] externalDirs = context.getExternalFilesDirs(null);
// 返回數組: [主外部存儲, 次級外部存儲(SD卡), ...]
// 遍歷查找可用、空間充足的目錄
for (File dir : externalDirs) {
    if (dir != null && dir.exists() && dir.canWrite()) {
        long freeSpace = dir.getUsableSpace();
        if (freeSpace > REQUIRED_SPACE) {
            // 使用此目錄
            break;
        }
    }
}

4. 內部存儲 (始終可用、私有、無需權限)


// 返回: /data/user/0/com.example.app/files/
File internalDir = context.getFilesDir();
// 返回: /data/user/0/com.example.app/cache/
File cacheDir = context.getCacheDir();
// 空間有限,僅存關鍵小文件

存儲選擇決策樹


File chooseStorageDir(Context context, long requiredSpace) {
    // 1. 嘗試應用專屬外部存儲 (首選)
    File[] externalDirs = context.getExternalFilesDirs(null);
    for (File dir : externalDirs) {
        if (dir != null && dir.getUsableSpace() >= requiredSpace) {
            return dir;
        }
    }
    
    // 2. 回退內部存儲
    File internalDir = context.getFilesDir();
    if (internalDir.getUsableSpace() >= requiredSpace) {
        return internalDir;
    }
    
    // 3. 最後嘗試緩存目錄 (可能被系統清理)
    return context.getCacheDir();
}

Android 版本差異處理

API 級別關鍵變化應對策略
19 (KitKat)引入 getExternalFilesDirs()、無需權限訪問專屬目錄優先使用專屬目錄
23 (Marshmallow)運行時權限動態申請 WRITE_EXTERNAL_STORAGE
29 (Android 10)分區存儲、限制公共目錄訪問遷移至 MediaStore、專屬目錄
30 (Android 11)強制分區存儲、MANAGE_EXTERNAL_STORAGE使用 MediaStore、SAF、專屬目錄
33 (Android 13)細粒度媒體權限 (READ_MEDIA_IMAGES 等)按類型申請權限

最佳實踐總結

  1. 優先使用 getExternalFilesDir():無需權限、應用專屬、自動清理、跨設備兼容
  2. 大文件檢查可用空間:dir.getUsableSpace() >= requiredBytes
  3. 多存儲卷遍歷選擇:getExternalFilesDirs() 返回所有可用卷
  4. 避免硬編碼路徑:/sdcard/、/storage/emulated/0/ 等不可靠
  5. 適配分區存儲:Android 10+ 使用 MediaStore 插入媒體文件
  6. 緩存文件用 getCacheDir():系統自動清理、無需手動管理

MediaStore 插入媒體文件示例 (Android 10+)


ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, "photo.jpg");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + "/MyApp");

Uri uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
try (OutputStream os = contentResolver.openOutputStream(uri)) {
    bitmap.compress(Bitmap.CompressFormat.JPEG, 90, os);
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved