Android多机型SD卡路径获取问题求助(参考assif_tiger相关讨论)
Hey there! I’ve fought this exact battle before—getting consistent SD card paths across the chaos of Android devices is such a pain, especially with manufacturers constantly deviating from "standard" paths post Android 6.0. Let’s walk through a solid, device-agnostic solution that should cover most scenarios:
First rule of thumb: never rely on paths like /sdcard/ or /storage/sdcard1/. Different brands (looking at you, Samsung, Xiaomi, Huawei) love to rename these, and newer Android versions use UUID-based paths like /storage/XXXX-XXXX/ for external storage. Always go through system-provided methods.
A. Prioritize Storage Access Framework (SAF) for Android 5.0+
SAF is Google’s official way to handle storage across devices, and it’s mandatory for Android 10+ (thanks to scoped storage). It lets users pick the storage location, and you interact with it via URIs instead of raw paths—no more guessing where the SD card is.
Here’s a quick snippet to kick off the SAF intent:
// In your activity/fragment private static final int REQUEST_CODE_SAF = 100; public void openSAF() { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); startActivityForResult(intent, REQUEST_CODE_SAF); } // Handle the result @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_SAF && resultCode == RESULT_OK) { Uri treeUri = data.getData(); // Persist the permission so it survives app restarts getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); // Now you can use this Uri to read/write files via ContentResolver } }
B. Fallback for Older Devices (Pre-Android 5.0)
For older versions, you can scan the /storage/ directory for valid removable storage, but you need to filter out internal storage and invalid paths:
public List<String> getLegacySDCardPaths() { List<String> validPaths = new ArrayList<>(); File storageRoot = new File("/storage/"); if (!storageRoot.exists() || !storageRoot.isDirectory()) { return validPaths; } File[] storageDirs = storageRoot.listFiles(); if (storageDirs == null) { return validPaths; } String internalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath(); for (File dir : storageDirs) { if (dir.isDirectory() && !dir.getAbsolutePath().equals(internalStoragePath)) { // Check if we can write to this path if (isPathWritable(dir.getAbsolutePath())) { validPaths.add(dir.getAbsolutePath()); } } } // Add the default external storage if it's removable if (Environment.isExternalStorageRemovable()) { validPaths.add(internalStoragePath); } return validPaths; } private boolean isPathWritable(String path) { File testFile = new File(path, "temp_test_file.tmp"); try { if (testFile.createNewFile()) { testFile.delete(); return true; } } catch (IOException e) { // Log the error if needed } return false; }
C. Validate Every Path
No matter which method you use, always verify that the path is actually writable (or readable, depending on your needs). The isPathWritable method above does this by trying to create a temporary file—if it works, the path is valid.
- Runtime Permissions: For Android 6.0+, you need to request
READ_EXTERNAL_STORAGEandWRITE_EXTERNAL_STORAGEdynamically before accessing storage. Don’t forget to handle the permission request result. - Scoped Storage (Android 10+): Direct file path access is blocked here, so SAF is your only reliable option. Trying to use raw paths will throw exceptions.
- Multiple SD Cards: Some devices support multiple external storage slots—make sure your code iterates through all valid volumes instead of just picking the first one.
内容的提问来源于stack exchange,提问作者Boosuro

