如何从视频文件的内容 URI 获取文件路径?

How do I get the file path from the content URI for video files?

我想附加来自 Android 存储的图像或视频文件。当我 select 来自图库的视频时,它 returns 内容 uri 路径

如何从内容 URI 中获取带有扩展名的 文件路径


我尝试了以下代码,但它 returns 在 lollipop 中为空:

void pickVideo() {
    Intent videoIntent = new Intent(Intent.ACTION_GET_CONTENT);
    videoIntent.setType("video/*");
    startActivityForResult(videoIntent, PICK_VIDEO_FILE);
}


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    try {
        if (resultCode != Activity.RESULT_OK)
            return;

        switch (requestCode) {
            case PICK_VIDEO_FILE:
                Uri videoUri = data.getData();
                String path = getRealPathFromURI(getContext(), videoUri);
                Log.d("Video uri path", "path" + path);
                if (mChooseFileDialogListener != null) {
                    mChooseFileDialogListener.onVideoClick(videoUri, HealthRecordViewModel.FILE_TYPE_VIDEO);
                }
                break;
        }
    }
}


public String getRealPathFromURI(Context context, Uri contentUri) {
    Cursor cursor = null;
    try {
        String[] proj = { MediaStore.Video.Media.DATA };
        cursor = context.getContentResolver().query(contentUri,  proj, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}

How to get the file path with extension?

你不知道。不要求用户 select 一段内容作为文件保存在您具有读取权限的位置。并且没有要求 ContentProvider 提供一些将 Uri 转换为文件路径的方法。

使用ContentResolveropenInputStream()读入Uri标识的内容。

这可能有帮助

import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.webkit.MimeTypeMap
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale.getDefault

/**
 * This class will create a temporary file in the cache if need.
 *
 * When the uri already have `file://` schema we don't need to create a new file.
 * The temporary file will always override a previous one, saving memory.
 * Using the cache memory(context.cacheDir) we guarantee to not leak memory
 *
 * @param context used to access Android APIs, like content resolve, it is your activity/fragment.
 * @param uri the URI to load the image from.
 * @param uniqueName If true, make each image cropped have a different file name, this could cause
 * memory issues, use wisely.
 *
 * @return string value of the File path.
 */
 fun getFilePathFromUri(context: Context, uri: Uri, uniqueName: Boolean): String =
    if (uri.path?.contains("file://") == true) uri.path!!
    else getFileFromContentUri(context, uri, uniqueName).path

private fun getFileFromContentUri(context: Context, contentUri: Uri, uniqueName: Boolean): File {
    // Preparing Temp file name
    val fileExtension = getFileExtension(context, contentUri) ?: ""
    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", getDefault()).format(Date())
    val fileName = ("temp_file_" + if (uniqueName) timeStamp else "") + ".$fileExtension"
    // Creating Temp file
    val tempFile = File(context.cacheDir, fileName)
    tempFile.createNewFile()
    // Initialize streams
    var oStream: FileOutputStream? = null
    var inputStream: InputStream? = null

    try {
        oStream = FileOutputStream(tempFile)
        inputStream = context.contentResolver.openInputStream(contentUri)

        inputStream?.let { copy(inputStream, oStream) }
        oStream.flush()
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        // Close streams
        inputStream?.close()
        oStream?.close()
    }

    return tempFile
}

private fun getFileExtension(context: Context, uri: Uri): String? =
    if (uri.scheme == ContentResolver.SCHEME_CONTENT)
        MimeTypeMap.getSingleton().getExtensionFromMimeType(context.contentResolver.getType(uri))
    else uri.path?.let { MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(File(it)).toString()) }

@Throws(IOException::class)
private fun copy(source: InputStream, target: OutputStream) {
    val buf = ByteArray(8192)
    var length: Int
    while (source.read(buf).also { length = it } > 0) {
        target.write(buf, 0, length)
    }
}