Get real path from Uri - DATA is deprecated in android Q

This question came up for me too a week ago.

My solution was to create an InputStream from the URI and then, from this, create an OutputStream by copying the contents of the input stream.

Note: You could call this method using an asynchronous call because copying extremely large files could have some delays and you won't want to block your 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();
}

I'm successfully implementing a method for retrieving the real path of an image from gallery by the Uri returned from ACTION_PICK intent.

That code may not work for all images. There is no requirement for DATA to point to a filesystem path that you can access.

Just like this answer.

FWIW, this was my answer to that question.

Only thing i found is this question. Didn't find a proper answer there though.

That technique wasn't particularly good and will no longer work, as Android has locked down /proc.

In the official docs, they recommend to use FileDescriptor instead, problem is i don't know exactly how.

The more general concept is that you use ContentResolver to work with the Uri, whether you get an InputStream (openInputStream()), OutputStream (openOutputStream()), or FileDescriptor. Consume the content using those things. If you have some API that absolutely needs a file, copy the content (e.g., from the InputStream) to a file that you control (e.g., in getCacheDir()).

As a bonus, now your code is also in position to use the Storage Access Framework (e.g., ACTION_OPEN_DOCUMENT) and the Internet (e.g., OkHttp), if and when that would be useful.