如何让Intent.ACTION_GET_CONTENT不显示0B空文件?附拍照存图问题
Hey there, let's fix this annoying issue step by step! First, let's clarify the root cause: when you use MediaStore.EXTRA_OUTPUT to specify the photo save path, even if the user cancels the camera action, the system still creates an empty file entry in MediaStore. That's where those 0B files are coming from. Here are two solid solutions for you:
方案一:从源头删除空文件(推荐)
This is the most thorough approach—we'll delete the empty file right when the user cancels or fails to take a photo. You just need to add logic in onActivityResult (or use registerForActivityResult if you're on AndroidX) to handle the camera result.
代码示例:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); final int IMAGE_CAPTURE_CODE = 1001; // Handle camera result if (requestCode == IMAGE_CAPTURE_CODE) { if (resultCode == RESULT_OK) { // Photo taken successfully, file is valid—no action needed } else { // User canceled or camera failed, delete the empty file if (image_uri != null) { // Option 1: Delete via ContentResolver to remove MediaStore entry getContentResolver().delete(image_uri, null, null); // Option 2: Delete the physical file directly (extra safety) try { File emptyFile = new File(getRealPathFromUri(image_uri)); if (emptyFile.exists() && emptyFile.length() == 0) { emptyFile.delete(); } } catch (Exception e) { e.printStackTrace(); } } } } // Keep your existing file picker result handling here if (requestCode == FILE_SELECT_CODE) { // Your original logic for selected files } } // Helper method to convert ContentUri to real file path private String getRealPathFromUri(Uri contentUri) { String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(contentUri, projection, null, null, null); if (cursor == null) return null; int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); String filePath = cursor.getString(columnIndex); cursor.close(); return filePath; }
Note: If you've migrated to AndroidX, it's better to use
ActivityResultContracts.TakePictureinstead ofstartActivityForResult—it has cleaner callbacks and makes handling cancellation easier.
方案二:让文件选择器过滤空文件
If you can't modify the camera logic for some reason, you can filter out empty files after they're selected, or build a custom picker that only shows valid files.
思路1:Filter after selection with ACTION_OPEN_DOCUMENT
ACTION_OPEN_DOCUMENT is the recommended way to pick files on Android 4.4+. You can check the file size right after selection:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == FILE_SELECT_CODE && resultCode == RESULT_OK) { Uri selectedUri = data.getData(); if (selectedUri != null) { DocumentFile docFile = DocumentFile.fromSingleUri(this, selectedUri); if (docFile != null && docFile.length() > 0) { // Valid non-empty file—proceed with your logic } else { Toast.makeText(this, "Please select a non-empty image file", Toast.LENGTH_SHORT).show(); } } } }
思路2:Build a custom file picker
If the system picker's limitations are too frustrating, you can create your own picker that queries MediaStore and filters out 0B files directly:
// Example query to get only non-empty images String[] projection = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.SIZE }; String selection = MediaStore.Images.Media.SIZE + " > ?"; String[] selectionArgs = {"0"}; Cursor cursor = getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null ); // Iterate through the cursor to display valid files in your custom UI
Final Thoughts
Go with 方案一 if you can—it fixes the problem at the source and prevents empty files from cluttering the MediaStore entirely.方案二 works as a backup if you can't adjust the camera flow, but it only filters after selection instead of hiding empty files from the picker.
内容的提问来源于stack exchange,提问作者rahul98

