从Uri获取真实路径-android Q

时间:2019-07-18 11:33:02

标签: android android-contentresolver

我正在成功实现一种方法,该方法可以根据Uri意图返回的ACTION_PICK从图库中检索图像的真实路径。这是一个示例:

// getRealPathFromURI(intent.getData());

private String getRealPathFromURI(Uri contentURI) {
    String result;
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) { // Source is Dropbox or other similar local file path
        result = contentURI.getPath();
    } else { 
        cursor.moveToFirst(); 
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); 
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}

就这样answer

最近将compileSdkVersion更新为29,显然每个人使用的 DATA 属性是deprecated。 在官方文档中,他们建议改为使用FileDescriptor,问题是我不知道该怎么做。
我发现的唯一东西就是这个question。在那里找不到合适的答案。

请使用建议的方法或其他任何方法帮助我解决弃用问题。

谢谢。

2 个答案:

答案 0 :(得分:2)

这个问题也是在一周前为我提出的。

我的解决方案是从URI创建一个InputStream,然后通过复制输入流的内容从中创建一个OutputStream

注意:您可以使用异步调用来调用此方法,因为复制非常大的文件可能会有一些延迟,并且您不想阻塞UI

@Nullable
public static String createCopyAndReturnRealPath(
       @NonNull Context context, @NonNull Uri uri) {
    final ContentResolver contentResolver = context.getContentResolver();
    if (contentResolver == null)
        return null;

    // Create file path inside app's data dir
    String filePath = context.getApplicationInfo().dataDir + File.separator
            + System.currentTimeMillis();

    File file = new File(filePath);
    try {
        InputStream inputStream = contentResolver.openInputStream(uri);
        if (inputStream == null)
            return null;

        OutputStream outputStream = new FileOutputStream(file);
        byte[] buf = new byte[1024];
        int len;
        while ((len = inputStream.read(buf)) > 0)
            outputStream.write(buf, 0, len);

        outputStream.close();
        inputStream.close();
    } catch (IOException ignore) {
        return null;
    }

    return file.getAbsolutePath();
}

答案 1 :(得分:1)

  

我正在成功实现一种方法,该方法可以根据ACTION_PICK意图返回的Uri从图库中检索图像的真实路径。

该代码可能不适用于所有图像。不需要DATA指向您可以访问的文件系统路径。

  

就像这个答案。

FWIW,this是我对这个问题的回答。

  

我唯一发现的就是这个问题。在那里找不到合适的答案。

由于Android已锁定/proc,因此该技术并不是特别好,将不再起作用。

  

在官方文档中,他们建议改为使用FileDescriptor,问题是我不知道怎么做。

更笼统的概念是,无论是否获得ContentResolverUri),InputStream({ {1}}或openInputStream()。使用这些东西消耗内容。如果您有一些绝对需要文件的API,请将内容(例如,从OutputStream复制到您控制的文件(例如,在openOutputStream()中)。

作为奖励,如果您愿意的话,现在您的代码也可以使用Storage Access Framework(例如FileDescriptor)和Internet(例如OkHttp)。