如何从Uri内容获取文件的绝对路径?Java Android Studio。

3

这种类型的Uri有两个例子:

"content://com.android.providers.downloads.documents/document/msf%3A33346" 和 "content://com.android.providers.downloads.documents/document/raw%3A%2Fstorage%2Femulated%2F0%2FDownload%2F2021-06-18Format%204.xls"

这些Uri会随着手机类型的不同而变化。我需要将Uri转换为文件路径,例如"storage/emulated/0/document/..."。

我曾经使用过一个看起来比较完整但并没有起作用的类,这个类出现在https://www.semicolonworld.com/question/45962/how-to-get-the-full-file-path-from-uri网页中,代码如下:

public class FileUtils {

/* Get uri related content real local file path. */
public static String getPath(Context ctx, Uri uri) {
    String ret;
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // Android OS above sdk version 19.
            ret = getUriRealPathAboveKitkat(ctx, uri);
        } else {
            // Android OS below sdk version 19
            ret = getRealPath(ctx.getContentResolver(), uri, null);
        }
    } catch (Exception e) {
        e.printStackTrace();
        Log.d("DREG", "FilePath Catch: " + e);
        ret = getFilePathFromURI(ctx, uri);
    }
    return ret;
}

private static String getFilePathFromURI(Context context, Uri contentUri) {
    //copy file and send new file path
    String fileName = getFileName(contentUri);
    if (!TextUtils.isEmpty(fileName)) {
        String TEMP_DIR_PATH = Environment.getExternalStorageDirectory().getPath();
        File copyFile = new File(TEMP_DIR_PATH + File.separator + fileName);
        Log.d("DREG", "FilePath copyFile: " + copyFile);
        copy(context, contentUri, copyFile);
        return copyFile.getAbsolutePath();
    }
    return null;
}

public static String getFileName(Uri uri) {
    if (uri == null) return null;
    String fileName = null;
    String path = uri.getPath();
    int cut = path.lastIndexOf('/');
    if (cut != -1) {
        fileName = path.substring(cut + 1);
    }
    return fileName;
}

public static void copy(Context context, Uri srcUri, File dstFile) {
    try {
        InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
        if (inputStream == null) return;
        OutputStream outputStream = new FileOutputStream(dstFile);
        IOUtils.copy(inputStream, outputStream); // org.apache.commons.io
        inputStream.close();
        outputStream.close();
    } catch (Exception e) { // IOException
        e.printStackTrace();
    }
}

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private static String getUriRealPathAboveKitkat(Context ctx, Uri uri) {
    String ret = "";

    if (ctx != null && uri != null) {

        if (isContentUri(uri)) {
            if (isGooglePhotoDoc(uri.getAuthority())) {
                ret = uri.getLastPathSegment();
            } else {
                ret = getRealPath(ctx.getContentResolver(), uri, null);
            }
        } else if (isFileUri(uri)) {
            ret = uri.getPath();
        } else if (isDocumentUri(ctx, uri)) {

            // Get uri related document id.
            String documentId = DocumentsContract.getDocumentId(uri);

            // Get uri authority.
            String uriAuthority = uri.getAuthority();

            if (isMediaDoc(uriAuthority)) {
                String idArr[] = documentId.split(":");
                if (idArr.length == 2) {
                    // First item is document type.
                    String docType = idArr[0];

                    // Second item is document real id.
                    String realDocId = idArr[1];

                    // Get content uri by document type.
                    Uri mediaContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    if ("image".equals(docType)) {
                        mediaContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    } else if ("video".equals(docType)) {
                        mediaContentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                    } else if ("audio".equals(docType)) {
                        mediaContentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                    }

                    // Get where clause with real document id.
                    String whereClause = MediaStore.Images.Media._ID + " = " + realDocId;

                    ret = getRealPath(ctx.getContentResolver(), mediaContentUri, whereClause);
                }

            } else if (isDownloadDoc(uriAuthority)) {
                // Build download uri.
                Uri downloadUri = Uri.parse("content://downloads/public_downloads");

                // Append download document id at uri end.
                Uri downloadUriAppendId = ContentUris.withAppendedId(downloadUri, Long.valueOf(documentId));

                ret = getRealPath(ctx.getContentResolver(), downloadUriAppendId, null);

            } else if (isExternalStoreDoc(uriAuthority)) {
                String idArr[] = documentId.split(":");
                if (idArr.length == 2) {
                    String type = idArr[0];
                    String realDocId = idArr[1];

                    if ("primary".equalsIgnoreCase(type)) {
                        ret = Environment.getExternalStorageDirectory() + "/" + realDocId;
                    }
                }
            }
        }
    }

    return ret;
}

/* Check whether this uri represent a document or not. */
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private static boolean isDocumentUri(Context ctx, Uri uri) {
    boolean ret = false;
    if (ctx != null && uri != null) {
        ret = DocumentsContract.isDocumentUri(ctx, uri);
    }
    return ret;
}

/* Check whether this uri is a content uri or not.
 *  content uri like content://media/external/images/media/1302716
 *  */
private static boolean isContentUri(Uri uri) {
    boolean ret = false;
    if (uri != null) {
        String uriSchema = uri.getScheme();
        if ("content".equalsIgnoreCase(uriSchema)) {
            ret = true;
        }
    }
    return ret;
}

/* Check whether this uri is a file uri or not.
 *  file uri like file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg
 * */
private static boolean isFileUri(Uri uri) {
    boolean ret = false;
    if (uri != null) {
        String uriSchema = uri.getScheme();
        if ("file".equalsIgnoreCase(uriSchema)) {
            ret = true;
        }
    }
    return ret;
}

/* Check whether this document is provided by ExternalStorageProvider. */
private static boolean isExternalStoreDoc(String uriAuthority) {
    boolean ret = false;

    if ("com.android.externalstorage.documents".equals(uriAuthority)) {
        ret = true;
    }

    return ret;
}

/* Check whether this document is provided by DownloadsProvider. */
private static boolean isDownloadDoc(String uriAuthority) {
    boolean ret = false;

    if ("com.android.providers.downloads.documents".equals(uriAuthority)) {
        ret = true;
    }

    return ret;
}

/* Check whether this document is provided by MediaProvider. */
private static boolean isMediaDoc(String uriAuthority) {
    boolean ret = false;

    if ("com.android.providers.media.documents".equals(uriAuthority)) {
        ret = true;
    }

    return ret;
}

/* Check whether this document is provided by google photos. */
private static boolean isGooglePhotoDoc(String uriAuthority) {
    boolean ret = false;

    if ("com.google.android.apps.photos.content".equals(uriAuthority)) {
        ret = true;
    }

    return ret;
}

/* Return uri represented document file real local path.*/
@SuppressLint("Recycle")
private static String getRealPath(ContentResolver contentResolver, Uri uri, String whereClause) {
    String ret = "";

    // Query the uri with condition.
    Cursor cursor = contentResolver.query(uri, null, whereClause, null, null);

    if (cursor != null) {
        boolean moveToFirst = cursor.moveToFirst();
        if (moveToFirst) {

            // Get columns name by uri type.
            String columnName = MediaStore.Images.Media.DATA;

            if (uri == MediaStore.Images.Media.EXTERNAL_CONTENT_URI) {
                columnName = MediaStore.Images.Media.DATA;
            } else if (uri == MediaStore.Audio.Media.EXTERNAL_CONTENT_URI) {
                columnName = MediaStore.Audio.Media.DATA;
            } else if (uri == MediaStore.Video.Media.EXTERNAL_CONTENT_URI) {
                columnName = MediaStore.Video.Media.DATA;
            }

            // Get column index.
            int columnIndex = cursor.getColumnIndex(columnName);

            // Get column value which is the uri related file local path.
            ret = cursor.getString(columnIndex);
        }
    }

    return ret;
}
}
1个回答

1

如果有人遇到这个问题,可以尝试使用这个函数,它对我很有效。

private fun getRealPathFromURI(contentUri: Uri, context: Context): String? {
    val proj = arrayOf(MediaStore.Images.Media.DATA)
    val loader = CursorLoader(context, contentUri, proj, null, null, null)
    val cursor: Cursor? = loader.loadInBackground()
    val columnIndex: Int = cursor
        ?.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) 
        ?: return null
    cursor.moveToFirst()
    val result: String? = cursor.getString(columnIndex)
    cursor.close()
    return result
}

他在问Java,而你给了一个Kotlin的解决方案... - Bosco Tsin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接