Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Get File Path from URI in Android Oreo (8.1) or above

Expected Behavior

When I am selecting the file which is stored inside "Download", it should able to retrieves its file name and path

Actual Behavior

When I am selecting the file which is stored inside "Download", it returns null.

Steps to Reproduce the Problem

  1. When picking file method is called, it displays the folders in Android
  2. Go to downloads, select a file
  3. It returns null in getting real path from URI

Here is the code what i implemented

public static String getPath(final Context context, final Uri uri) {
   String id = DocumentsContract.getDocumentId(uri);
   if (!TextUtils.isEmpty(id)) {
      if (id.startsWith("raw:")) {
          return id.replaceFirst("raw:", "");
      }
      try {
         final boolean isOreo = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
         String stringContentURI;
         Uri contentUri;
         if(isOreo){ 
            stringContentURI = "content://downloads/my_downloads";
         }else{
            stringContentURI = "content://downloads/public_downloads";
         }
         contentUri = ContentUris.withAppendedId(
                    Uri.parse(stringContentURI), Long.valueOf(id));
         return getDataColumn(context, contentUri, null, null);
      } catch (NumberFormatException e) {
         return null;
      }
   }
}

public static String getDataColumn(Context context, Uri uri, String selection,
                                   String[] selectionArgs) {
    Cursor cursor = null;
    final String column = "_data";
    final String[] projection = {   column};
    try {
        cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                null);
        if (cursor != null && cursor.moveToFirst()) {
            final int index = cursor.getColumnIndexOrThrow(column);
            return cursor.getString(index);
        }
    } finally {
        if (cursor != null)
            cursor.close();
    }
    return null;
}

However, it is working when selecting file from other folders in Android device

Please advise. Thanks everyone :)

like image 798
ryosu Avatar asked Oct 12 '18 08:10

ryosu


People also ask

How to get the full file path from Uri in Android?

How to get the Full file path from URI in Android. File Utils Class help to get full path from given Uri. ? final String selection = "_id=?"; * Get the value of the data column for this Uri. This is useful for * MediaStore Uris, and other file-based ContentProviders. * @param context The context. * @param uri The Uri to query.

How to get the real path from the URI of audio?

On Android (Lollipop),To convert the uri to real path is working fine using cursor but for Oreo devices I am not able to get the real path from the Uri of this audio. I solved it. Simply call this getPathFromURI method and it will return the file path

Is the contentprovider Uri a real file path?

The ContentProvider URI is not a real android file path URI ( such as file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg ), it is a content provider style URI ( such as content://media/external/images/media/1302716 ).

How do I access other app created files in Android?

If your Android app wants to access other app created files, you should get the file from its ContentProvider with a content URI. The ContentProvider URI is not a real android file path URI ( file:///storage/41B7-12F1/DCIM/Camera/IMG_20180211_095139.jpg ), it is a content provider style URI ( content://media/external/images/media/1302716 ).


1 Answers

For now, the best approach for getting path is :

Getting physical file from URI as InputStream, ContentResolver.openInputStream() allow you to access the contents of a file without knowing its real path

String id = DocumentsContract.getDocumentId(uri);
InputStream inputStream = getContentResolver().openInputStream(uri);

then write it as a temporary file in cached storage

File file = new File(getCacheDir().getAbsolutePath()+"/"+id);
writeFile(inputStream, file);
String filePath = file.getAbsolutePath();

Here is the method to write temporary file into cached storage

void writeFile(InputStream in, File file) {
     OutputStream out = null;
     try {
          out = new FileOutputStream(file);
          byte[] buf = new byte[1024];
          int len;
          while((len=in.read(buf))>0){
            out.write(buf,0,len);
          }
     } catch (Exception e) {
          e.printStackTrace();
     }
     finally {
          try {
            if ( out != null ) {
                 out.close();
            }
            in.close();
          } catch ( IOException e ) {
               e.printStackTrace();
          }
     }
}

Not sure if its the best way to do, but the code is working properly :D

like image 191
ryosu Avatar answered Sep 21 '22 05:09

ryosu