You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中通过URI获取视频文件大小返回0问题求助

It’s common to run into issues with content URIs when trying to get file sizes on Android—here’s why your current approach isn’t working and how to fix it:

Why Your java.net.URI Approach Fails

When you get a video URI from the camera intent or gallery, it’s almost always a content URI (looks like content://media/external/video/media/XXX) rather than a direct file URI. A content URI points to media stored in the system’s MediaStore, not a physical file path that java.net.URI can resolve to a valid File object. That’s why you’re getting a size of 0—your code is trying to access a file that doesn’t exist at that "path."

Solution: Get Video Size Using ContentResolver

The correct way to retrieve the size of a video (whether from gallery or camera) is to use Android’s ContentResolver to query the MediaStore, or directly read from the URI if needed. Here’s how to implement this end-to-end:

1. Set Up Activity Result Handlers (Modern Approach)

First, use the Activity Result API (recommended for Android X and above) to handle video selection and recording:

// For picking video from gallery
private ActivityResultLauncher<String> pickVideoLauncher;

// For recording video with camera
private ActivityResultLauncher<Uri> recordVideoLauncher;
private File tempVideoFile;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Initialize gallery pick launcher
    pickVideoLauncher = registerForActivityResult(
            new ActivityResultContracts.GetContent(),
            uri -> {
                if (uri != null) {
                    long videoSize = getVideoSize(uri);
                    checkVideoSizeLimit(videoSize);
                }
            });

    // Initialize camera record launcher
    recordVideoLauncher = registerForActivityResult(
            new ActivityResultContracts.TakeVideo(),
            isSuccess -> {
                if (isSuccess && tempVideoFile != null) {
                    // For camera-recorded video, get size directly from the temp file
                    long videoSize = tempVideoFile.length();
                    checkVideoSizeLimit(videoSize);
                }
            });
}

2. Create Temporary File for Camera Recording

When using the camera intent, you need to provide a URI where the camera will save the video. Use FileProvider (to comply with scoped storage) to create a valid content URI:

private File createTempVideoFile() throws IOException {
    // Create a unique temporary file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
    String videoFileName = "VID_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_MOVIES);
    return File.createTempFile(videoFileName, ".mp4", storageDir);
}

// Call this method to start recording
private void startCameraRecording() {
    try {
        tempVideoFile = createTempVideoFile();
        Uri videoUri = FileProvider.getUriForFile(
                this,
                "com.yourpackage.name.fileprovider", // Replace with your FileProvider authority
                tempVideoFile
        );
        recordVideoLauncher.launch(videoUri);
    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(this, "Failed to create temp file", Toast.LENGTH_SHORT).show();
    }
}

3. Implement the Video Size Calculation Method

This method handles both content URIs (from gallery) and file URIs (from camera temp file):

private long getVideoSize(Uri videoUri) {
    long size = 0;
    ContentResolver resolver = getContentResolver();

    if (ContentResolver.SCHEME_CONTENT.equals(videoUri.getScheme())) {
        // Query MediaStore for the video size
        try (Cursor cursor = resolver.query(
                videoUri,
                new String[]{MediaStore.Video.Media.SIZE},
                null,
                null,
                null
        )) {
            if (cursor != null && cursor.moveToFirst()) {
                size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE));
            }
        } catch (Exception e) {
            e.printStackTrace();
            // Fallback: If query fails, read the input stream to get size
            try (InputStream inputStream = resolver.openInputStream(videoUri)) {
                if (inputStream != null) {
                    size = inputStream.available();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    } else if (ContentResolver.SCHEME_FILE.equals(videoUri.getScheme())) {
        // Handle file URI (e.g., temp file from camera)
        File videoFile = new File(videoUri.getPath());
        size = videoFile.length();
    }

    return size;
}

4. Check Size and Show Toast

Finally, add the logic to compare the size against your 5MB limit:

private void checkVideoSizeLimit(long videoSize) {
    final long MAX_VIDEO_SIZE = 5 * 1024 * 1024; // 5MB in bytes

    if (videoSize > MAX_VIDEO_SIZE) {
        Toast.makeText(this, "Video size exceeds 5MB", Toast.LENGTH_LONG).show();
    }
}

5. Required Setup for FileProvider

To use FileProvider, add this to your AndroidManifest.xml:

<application ...>
    <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>
</application>

Then create a res/xml/file_paths.xml file:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-files-path name="my_movies" path="Movies/" />
</paths>

Key Notes

  • Permissions: For camera recording, you’ll need to request the CAMERA permission (and WRITE_EXTERNAL_STORAGE if targeting Android 9 or lower).
  • Scoped Storage: On Android 10+, direct file access is restricted, so using ContentResolver or FileProvider is mandatory for accessing media files.
  • Fallback Logic: The getContentResolver().openInputStream() fallback ensures you can get the size even if the MediaStore query fails (e.g., for videos stored in cloud providers).

This approach should correctly retrieve the video size every time, eliminating the 0 value you were seeing earlier.

内容的提问来源于stack exchange,提问作者Usman Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:51:33