Intent.ACTION_GET_CONTENT 配合 setType("image/*") 僅能選圖片,需選擇任意類型文件 (PDF、ZIP、APK 等)。
Android 系統不提供統一的「所有文件」選擇器 UI。ACTION_GET_CONTENT 依賴安裝的應用響應,僅有圖庫/文件管理器等應用註冊了特定 MIME 類型。
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*"); // 理論匹配所有類型
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(intent, "選擇文件"), REQUEST_CODE);
缺點:很多文件管理器未正確註冊 */*,彈出選擇器為空或僅顯示圖庫。
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// 明確列出常見類型,提高匹配率
String[] mimeTypes = {
"application/pdf",
"application/zip",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.android.package-archive", // APK
"text/plain",
"image/*",
"video/*",
"audio/*"
};
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(intent, "選擇文件"), REQUEST_CODE);
// 打開系統文件選擇器 (DocumentPicker)
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*"); // 或具體類型
// 可選:指定初始目錄 (API 21+)
intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, DocumentsContract.buildRootsUri("com.android.externalstorage.documents"));
startActivityForResult(intent, REQUEST_CODE_DOCUMENT);
// onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
// 獲取持久化權限
getContentResolver().takePersistableUriPermission(uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
// 使用 ContentResolver 讀取流
InputStream is = getContentResolver().openInputStream(uri);
}
}
優勢:系統級 UI、支援雲端/網絡存儲、持久化 URI 權限、無需讀取存儲權限。
public void openFilePicker() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
// API 19+ 優先用 SAF
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, REQUEST_SAF);
} else {
// 老版本兜底
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(Intent.createChooser(intent, "選擇文件"), REQUEST_LEGACY);
}
}
| 方案 | 需權限 | 備註 |
|---|---|---|
| ACTION_GET_CONTENT | 無 (臨時 URI 權限) | 返回 URI 臨時有效 |
| ACTION_OPEN_DOCUMENT | 無 (持久化 URI 權限) | takePersistableUriPermission 長期訪問 |
| 文件管理器 App | READ_EXTERNAL_STORAGE | Android 10+ 分區存儲限制 |