从onActivityResult的Intent获取视频路径时触发File not found异常求助
Hey there! Let's get that video capture and path access issue sorted out. The FileNotFoundException you're hitting is super common with Android's video capture API, mainly because of how the system handles file URIs across different OS versions—especially starting from Android 7.0 (API 24) where direct file URIs are restricted, and the default camera app often returns a content:// URI instead of a raw file path.
Why This Happens
When you use MediaStore.ACTION_VIDEO_CAPTURE without specifying an output file, the camera app returns a content:// URI in the result intent. Trying to convert this URI directly to a file path (like calling uri.getPath()) won't work because it points to a content provider entry, not a physical file on the filesystem. On newer Android versions, this also triggers security restrictions that block direct access to the file.
Solution 1: Get the Real File Path from the Content URI
If you want to stick with the default camera output behavior, use this utility method to convert the returned content:// URI to a valid file path. Add this to your activity:
private String getRealPathFromUri(Context context, Uri uri) { String filePath = ""; if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { Cursor cursor = null; try { cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Video.Media.DATA}, null, null, null); if (cursor != null && cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndex(MediaStore.Video.Media.DATA); filePath = cursor.getString(columnIndex); } } finally { if (cursor != null) { cursor.close(); } } } else if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { filePath = uri.getPath(); } return filePath; }
Then use it in your onActivityResult (note: for newer Android versions, you can also migrate to the ActivityResultContracts API):
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) { Uri videoUri = data.getData(); String realPath = getRealPathFromUri(this, videoUri); // Now you can use realPath to access the video file if (!TextUtils.isEmpty(realPath)) { File videoFile = new File(realPath); // Proceed with upload to server } else { // Handle case where path couldn't be retrieved Toast.makeText(this, "Failed to get video path", Toast.LENGTH_SHORT).show(); } } }
Important Note: Permissions
For Android 6.0 (API 23) and above, you need to request the READ_EXTERNAL_STORAGE permission dynamically before accessing the file path.
Solution 2: Specify a Custom Output File (Recommended)
A more reliable approach is to tell the camera app exactly where to save the video file. This avoids dealing with content:// URIs entirely, and you'll already know the file path once the capture is done.
Step 1: Create a Method to Generate a Video File
Add this to your activity to create a unique video file in your app's private storage (no dynamic permissions needed here):
private File createVideoFile() throws IOException { // Generate a unique filename using timestamp String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String videoFileName = "CAPTURED_VIDEO_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_MOVIES); // Create a temporary file with .mp4 extension return File.createTempFile( videoFileName, ".mp4", storageDir ); }
Step 2: Update the recordVideo Method
Modify your video capture intent to use FileProvider (required for Android 7.0+) to pass the file URI to the camera:
private static final int REQUEST_VIDEO_CAPTURE = 1; private File mVideoFile; // Store the video file reference private void recordVideo(){ Intent takeVideoIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); if (takeVideoIntent.resolveActivity(getPackageManager()) != null) { try { mVideoFile = createVideoFile(); } catch (IOException ex) { // Handle file creation failure (e.g., no storage space) ex.printStackTrace(); Toast.makeText(this, "Failed to create video file", Toast.LENGTH_SHORT).show(); return; } // Use FileProvider to get a valid URI for the file Uri videoUri = FileProvider.getUriForFile( this, "com.yourpackage.name.fileprovider", // Replace with your app's authority mVideoFile ); takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, videoUri); // Grant temporary permission to the camera app to write to the file takeVideoIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); startActivityForResult(takeVideoIntent, REQUEST_VIDEO_CAPTURE); } }
Step 3: Register FileProvider in AndroidManifest.xml
Add this inside the <application> tag:
<provider android:name="androidx.core.content.FileProvider" android:authorities="com.yourpackage.name.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
Step 4: Create the file_paths.xml Resource
Create a res/xml directory if it doesn't exist, then add file_paths.xml:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="captured_videos" path="Movies/" /> </paths>
Step 5: Handle the Result in onActivityResult
Since you specified the output file, you don't need to get data from the intent—just use the mVideoFile reference directly:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_VIDEO_CAPTURE && resultCode == RESULT_OK) { // mVideoFile already contains the path to the captured video if (mVideoFile.exists()) { // Proceed with uploading mVideoFile to your server } else { Toast.makeText(this, "Video file not found", Toast.LENGTH_SHORT).show(); } } }
This method is more reliable because you have full control over where the video is saved, and you avoid the pitfalls of content URI path conversion.
Give these steps a shot—either solution should fix your FileNotFoundException issue. Let me know if you hit any snags!
内容的提问来源于stack exchange,提问作者Jayant Kumar

