title: Trouble extracting path from Uri in Android app
body: <p>I'm using some code from a helpful stack exchange user to browse and select files on my Android. However, when selecting a file from a subfolder in Download, I get an error. Is there a way to extract the path from the Uri in the form: /storage/emulated/0/Download/subfolder/filename.gpx?</p>
  <p>In the &quot;Downloads Provider&quot; section below, why is the /Download/ part hard coded? <br>
  When I select the file <code>Download/subfolder/filename.gpx</code>, getPath returns <code>Download/filename.gpx</code> resulting in an IOException, no file found.</p>
  <p>Here's the line I have an issue with: <br>
  <code>String path = Environment.getExternalStorageDirectory().toString() + &quot;/Download/&quot; + fileName;</code>
  <br>
  <br></p>
  <pre><code>import android.annotation.SuppressLint;
  import android.content.ContentUris;
  import android.content.Context;
  import android.content.Intent;
  import android.database.Cursor;
  import android.net.Uri;
  import android.os.Build;
  import android.os.Environment;
  import android.provider.DocumentsContract;
  import android.provider.MediaStore;
  import android.provider.OpenableColumns;
  import android.text.TextUtils;
  import android.util.Log;
  import android.webkit.MimeTypeMap;
  import android.widget.Toast;
  
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.InputStream;
  import java.util.ArrayList;
  import java.util.List;
  
  public class FileUtils {
      private static Uri contentUri = null;
  
      Context context;
  
      public FileUtils( Context context) {
          this.context=context;
      }
  
      @SuppressLint(&quot;NewApi&quot;)
      public static String getPath( final Uri uri) {
          // check here to KITKAT or new version
          final boolean isKitKat = Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.KITKAT;
          String selection = null;
          String[] selectionArgs = null;
          // DocumentProvider
          if (isKitKat ) {
              // ExternalStorageProvider
  
             if (isExternalStorageDocument(uri)) {
                  final String docId = DocumentsContract.getDocumentId(uri);
                  final String[] split = docId.split(&quot;:&quot;);
                  final String type = split[0];
  
                  String fullPath = getPathFromExtSD(split);
                  if (fullPath != &quot;&quot;) {
                      return fullPath;
                  } else {
                      return null;
                  }
              }
  
  
              // DownloadsProvider
  
              if (isDownloadsDocument(uri)) {
  
                  if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) {
                      final String id;
                      Cursor cursor = null;
                      try {
                          cursor = context.getContentResolver().query(uri, new String[]{MediaStore.MediaColumns.DISPLAY_NAME}, null, null, null);
                          if (cursor != null &amp;&amp; cursor.moveToFirst()) {
                              String fileName = cursor.getString(0);
                              String path = Environment.getExternalStorageDirectory().toString() + &quot;/Download/&quot; + fileName;
                              if (!TextUtils.isEmpty(path)) {
                                  return path;
                              }
                          }
                      }
                      finally {
                          if (cursor != null)
                              cursor.close();
                      }
                      id = DocumentsContract.getDocumentId(uri);
                      if (!TextUtils.isEmpty(id)) {
                          if (id.startsWith(&quot;raw:&quot;)) {
                              return id.replaceFirst(&quot;raw:&quot;, &quot;&quot;);
                          }
                          String[] contentUriPrefixesToTry = new String[]{
                                  &quot;content://downloads/public_downloads&quot;,
                                  &quot;content://downloads/my_downloads&quot;
                          };
                          for (String contentUriPrefix : contentUriPrefixesToTry) {
                              try {
                                  final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
  
  
                                  return getDataColumn(context, contentUri, null, null);
                              } catch (NumberFormatException e) {
                                  //In Android 8 and Android P the id is not a number
                                  return uri.getPath().replaceFirst(&quot;^/document/raw:&quot;, &quot;&quot;).replaceFirst(&quot;^raw:&quot;, &quot;&quot;);
                              }
                          }
  
  
                      }
                  }
                  else {
                      final String id = DocumentsContract.getDocumentId(uri);
  
                      if (id.startsWith(&quot;raw:&quot;)) {
                          return id.replaceFirst(&quot;raw:&quot;, &quot;&quot;);
                      }
                      try {
                          contentUri = ContentUris.withAppendedId(
                                  Uri.parse(&quot;content://downloads/public_downloads&quot;), Long.valueOf(id));
                      }
                      catch (NumberFormatException e) {
                          e.printStackTrace();
                      }
                      if (contentUri != null) {
  
                          return getDataColumn(context, contentUri, null, null);
                      }
                  }
              }
  
  
              // MediaProvider
             if (isMediaDocument(uri)) {
                  final String docId = DocumentsContract.getDocumentId(uri);
                  final String[] split = docId.split(&quot;:&quot;);
                  final String type = split[0];
  
                  Uri contentUri = null;
  
                  if (&quot;image&quot;.equals(type)) {
                      contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                  } else if (&quot;video&quot;.equals(type)) {
                      contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                  } else if (&quot;audio&quot;.equals(type)) {
                      contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                  }
                  selection = &quot;_id=?&quot;;
                  selectionArgs = new String[]{split[1]};
  
  
                  return getDataColumn(context, contentUri, selection,
                          selectionArgs);
              }
  
             if (isGoogleDriveUri(uri)) {
                  return getDriveFilePath(uri);
              }
  
             if(isWhatsAppFile(uri)){
                  return getFilePathForWhatsApp(uri);
              }
  
  
             if (&quot;content&quot;.equalsIgnoreCase(uri.getScheme())) {
  
                  if (isGooglePhotosUri(uri)) {
                      return uri.getLastPathSegment();
                  }
                  if (isGoogleDriveUri(uri)) {
                      return getDriveFilePath(uri);
                  }
                  if( Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.Q)
                  {
  
                      // return getFilePathFromURI(context,uri);
                      return copyFileToInternalStorage(uri,&quot;userfiles&quot;);
                      // return getRealPathFromURI(context,uri);
                  }
                  else
                  {
                      return getDataColumn(context, uri, null, null);
                  }
  
             }
             if (&quot;file&quot;.equalsIgnoreCase(uri.getScheme())) {
                  return uri.getPath();
              }
          }
          else {
  
              if(isWhatsAppFile(uri)){
                  return getFilePathForWhatsApp(uri);
              }
  
              if (&quot;content&quot;.equalsIgnoreCase(uri.getScheme())) {
                  String[] projection = {
                          MediaStore.Images.Media.DATA
                  };
                  Cursor cursor = null;
                  try {
                      cursor = context.getContentResolver()
                              .query(uri, projection, selection, selectionArgs, null);
                      int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                      if (cursor.moveToFirst()) {
                          return cursor.getString(column_index);
                      }
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }
  
  
  
  
          return null;
      }
  
      private  boolean fileExists(String filePath) {
          File file = new File(filePath);
  
          return file.exists();
      }
  
      private String getPathFromExtSD(String[] pathData) {
          final String type = pathData[0];
          final String relativePath = &quot;/&quot; + pathData[1];
          String fullPath = &quot;&quot;;
  
          // on my Sony devices (4.4.4 &amp; 5.1.1), `type` is a dynamic string
          // something like &quot;71F8-2C0A&quot;, some kind of unique id per storage
          // don't know any API that can get the root path of that storage based on its id.
          //
          // so no &quot;primary&quot; type, but let the check here for other devices
          if (&quot;primary&quot;.equalsIgnoreCase(type)) {
              fullPath = Environment.getExternalStorageDirectory() + relativePath;
              if (fileExists(fullPath)) {
                  return fullPath;
              }
          }
  
          // Environment.isExternalStorageRemovable() is `true` for external and internal storage
          // so we cannot relay on it.
          //
          // instead, for each possible path, check if file exists
          // we'll start with secondary storage as this could be our (physically) removable sd card
          fullPath = System.getenv(&quot;SECONDARY_STORAGE&quot;) + relativePath;
          if (fileExists(fullPath)) {
              return fullPath;
          }
  
          fullPath = System.getenv(&quot;EXTERNAL_STORAGE&quot;) + relativePath;
          if (fileExists(fullPath)) {
              return fullPath;
          }
  
          return fullPath;
      }
  
      private String getDriveFilePath(Uri uri) {
          Uri returnUri = uri;
          Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
          /*
           * Get the column indexes of the data in the Cursor,
           *     * move to the first row in the Cursor, get the data,
           *     * and display it.
           * */
          int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
          int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
          returnCursor.moveToFirst();
          String name = (returnCursor.getString(nameIndex));
          String size = (Long.toString(returnCursor.getLong(sizeIndex)));
          File file = new File(context.getCacheDir(), name);
          try {
              InputStream inputStream = context.getContentResolver().openInputStream(uri);
              FileOutputStream outputStream = new FileOutputStream(file);
              int read = 0;
              int maxBufferSize = 1 * 1024 * 1024;
              int bytesAvailable = inputStream.available();
  
              //int bufferSize = 1024;
              int bufferSize = Math.min(bytesAvailable, maxBufferSize);
  
              final byte[] buffers = new byte[bufferSize];
              while ((read = inputStream.read(buffers)) != -1) {
                  outputStream.write(buffers, 0, read);
              }
              Log.e(&quot;File Size&quot;, &quot;Size &quot; + file.length());
              inputStream.close();
              outputStream.close();
              Log.e(&quot;File Path&quot;, &quot;Path &quot; + file.getPath());
              Log.e(&quot;File Size&quot;, &quot;Size &quot; + file.length());
          } catch (Exception e) {
              Log.e(&quot;Exception&quot;, e.getMessage());
          }
          return file.getPath();
      }
  
      /***
       * Used for Android Q+
       * @param uri
       * @param newDirName if you want to create a directory, you can set this variable
       * @return
       */
      private String copyFileToInternalStorage(Uri uri,String newDirName) {
          Uri returnUri = uri;
  
          Cursor returnCursor = context.getContentResolver().query(returnUri, new String[]{
                  OpenableColumns.DISPLAY_NAME,OpenableColumns.SIZE
          }, null, null, null);
  
  
          /*
           * Get the column indexes of the data in the Cursor,
           *     * move to the first row in the Cursor, get the data,
           *     * and display it.
           * */
          int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
          int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
          returnCursor.moveToFirst();
          String name = (returnCursor.getString(nameIndex));
          String size = (Long.toString(returnCursor.getLong(sizeIndex)));
  
          File output;
          if(!newDirName.equals(&quot;&quot;)) {
              File dir = new File(context.getFilesDir() + &quot;/&quot; + newDirName);
              if (!dir.exists()) {
                  dir.mkdir();
              }
              output = new File(context.getFilesDir() + &quot;/&quot; + newDirName + &quot;/&quot; + name);
          }
          else{
              output = new File(context.getFilesDir() + &quot;/&quot; + name);
          }
          try {
              InputStream inputStream = context.getContentResolver().openInputStream(uri);
              FileOutputStream outputStream = new FileOutputStream(output);
              int read = 0;
              int bufferSize = 1024;
              final byte[] buffers = new byte[bufferSize];
              while ((read = inputStream.read(buffers)) != -1) {
                  outputStream.write(buffers, 0, read);
              }
  
              inputStream.close();
              outputStream.close();
  
          }
          catch (Exception e) {
  
              Log.e(&quot;Exception&quot;, e.getMessage());
          }
  
          return output.getPath();
      }
  
      private String getFilePathForWhatsApp(Uri uri){
              return  copyFileToInternalStorage(uri,&quot;whatsapp&quot;);
      }
  
      private String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
          Cursor cursor = null;
          final String column = &quot;_data&quot;;
          final String[] projection = {column};
  
          try {
              cursor = context.getContentResolver().query(uri, projection,
                      selection, selectionArgs, null);
  
              if (cursor != null &amp;&amp; cursor.moveToFirst()) {
                  final int index = cursor.getColumnIndexOrThrow(column);
                  return cursor.getString(index);
              }
          }
          finally {
              if (cursor != null)
                  cursor.close();
          }
  
          return null;
      }
  
      private  boolean isExternalStorageDocument(Uri uri) {
          return &quot;com.android.externalstorage.documents&quot;.equals(uri.getAuthority());
      }
  
      private  boolean isDownloadsDocument(Uri uri) {
          return &quot;com.android.providers.downloads.documents&quot;.equals(uri.getAuthority());
      }
  
      private  boolean isMediaDocument(Uri uri) {
          return &quot;com.android.providers.media.documents&quot;.equals(uri.getAuthority());
      }
  
      private  boolean isGooglePhotosUri(Uri uri) {
          return &quot;com.google.android.apps.photos.content&quot;.equals(uri.getAuthority());
      }
  
      public boolean isWhatsAppFile(Uri uri){
          return &quot;com.whatsapp.provider.media&quot;.equals(uri.getAuthority());
      }
  
      private  boolean isGoogleDriveUri(Uri uri) {
          return &quot;com.google.android.apps.docs.storage&quot;.equals(uri.getAuthority()) || &quot;com.google.android.apps.docs.storage.legacy&quot;.equals(uri.getAuthority());
      }
  
  
  }
  </code></pre>