Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

// 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;
}

Just like this answer.

Recently updated the compileSdkVersion to 29 and apparently the DATA attribute everyone's using is deprecated. In the official docs, they recommend to use FileDescriptor instead, problem is i don't know exactly how.
Only thing i found is this question. Didn't find a proper answer there though.

Please help me overcome that deprecation issue with a solution using the suggested way or any other way.

Thank you.


Update:

Followed @CommonsWare's answer and copied the returned Uri (of an image the user picked) to a local directory, using context.getContentResolver.openInputStream(Uri).

Even tried retrieving a file from Google Drive - and it worked. Only problem was the long time it took (about 20 sec for 5MB file).

As a bonus, i was cleared to remove external storage permissions, which one doesn't need for using app's local directories.

No more externals paths for me!

like image 806
ronginat Avatar asked Jul 18 '19 11:07

ronginat


People also ask

How do I get full path from URI?

Uri uri = data. getData(); File file = new File(uri. getPath());//create path from uri final String[] split = file. getPath().

What is a URI in Android?

A URI is a uniform resource identifier while a URL is a uniform resource locator. Hence every URL is a URI, abstractly speaking, but not every URI is a URL. This is because there is another subcategory of URIs, uniform resource names (URNs), which name resources but do not specify how to locate them.


1 Answers

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();
}
like image 150
dafNou Avatar answered Oct 03 '22 06:10

dafNou