SoFunction
Updated on 2025-04-09

Implementation of Uri to path method above Android 7.0 (verified)

There are many ways to turn Uri paths on the Internet, but they are basically only applicable to very few Uri values, and may have no results (for example, for non-local files indexed by MediaStore), or may have no results (for example, for files on removable storage).

Solution

Use ContentResolver and openInputStream() to get InputStream on the content identified by Uri. Copy the content using InputStream and FileOutputStream on the controlled file and then use the file.

The code is as follows:

private static String getFilePathForN(Context context, Uri uri) {
  try {
    Cursor returnCursor = ().query(uri, null, null, null, null);
    int nameIndex = (OpenableColumns.DISPLAY_NAME);
    ();
    String name = ((nameIndex));
    File file = new File((), name);
    InputStream inputStream = ().openInputStream(uri);
    FileOutputStream outputStream = new FileOutputStream(file);
    int read = 0;
    int maxBufferSize = 1 * 1024 * 1024;
    int bytesAvailable = ();
    int bufferSize = (bytesAvailable, maxBufferSize);
    final byte[] buffers = new byte[bufferSize];
    while ((read = (buffers)) != -1) {
      (buffers, 0, read);
    }
    ();
    ();
    ();
    return ();
  } catch (Exception e) {
    ();
  }
  return null;
}

Attach the whole system code:

/**
  * File Uri to path (compatible with mobile phones of each brand)
  */
public class PathUtils {
  /**
    * Android 7.0 or above processing methods
    */
  private static String getFilePathForN(Context context, Uri uri) {
    try {
      Cursor returnCursor = ().query(uri, null, null, null, null);
      int nameIndex = (OpenableColumns.DISPLAY_NAME);
      ();
      String name = ((nameIndex));
      File file = new File((), name);
      InputStream inputStream = ().openInputStream(uri);
      FileOutputStream outputStream = new FileOutputStream(file);
      int read = 0;
      int maxBufferSize = 1 * 1024 * 1024;
      int bytesAvailable = ();

      int bufferSize = (bytesAvailable, maxBufferSize);

      final byte[] buffers = new byte[bufferSize];
      while ((read = (buffers)) != -1) {
        (buffers, 0, read);
      }
      ();
      ();
      ();
      return ();
    } catch (Exception e) {
      ();
    }
    return null;
  }

  /**
    * Full platform processing method
    */
  public static String getPath(final Context context, final Uri uri) throws Exception {

    final boolean isKitKat = .SDK_INT >= Build.VERSION_CODES.KITKAT;
    final boolean isN = .SDK_INT >= Build.VERSION_CODES.N;

    if (isN) {
      return getFilePathForN(context, uri);
    }

    // DocumentProvider
    if (isKitKat && (context, uri)) {
      // ExternalStorageProvider
      if (isExternalStorageDocument(uri)) {
        final String docId = (uri);
        final String[] split = (":");
        final String type = split[0];

        if ("primary".equalsIgnoreCase(type)) {
          return () + "/" + split[1];
        }

      }
      // DownloadsProvider
      else if (isDownloadsDocument(uri)) {

        final String id = (uri);
        final Uri contentUri = (
            ("content://downloads/public_downloads"), (id));

        return getDataColumn(context, contentUri, null, null);
      }
      // MediaProvider
      else if (isMediaDocument(uri)) {
        final String docId = (uri);
        final String[] split = (":");
        final String type = split[0];

        Uri contentUri = null;
        if ("image".equals(type)) {
          contentUri = .EXTERNAL_CONTENT_URI;
        } else if ("video".equals(type)) {
          contentUri = .EXTERNAL_CONTENT_URI;
        } else if ("audio".equals(type)) {
          contentUri = .EXTERNAL_CONTENT_URI;
        }

        final String selection = "_id=?";
        final String[] selectionArgs = new String[] {
            split[1]
        };

        return getDataColumn(context, contentUri, selection, selectionArgs);
      }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(())) {
      return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(())) {
      return ();
    }

    return null;
  }

  /**
    * Gets the value of this Uri's data column.  This is very useful for MediaStore uri and other file-based content providers.
    */
  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 = ().query(uri, projection, selection, selectionArgs,
          null);
      if (cursor != null && ()) {
        final int column_index = (column);
        return (column_index);
      }
    } catch (IllegalArgumentException e){
      //do nothing
    } finally {
      if (cursor != null)
        ();
    }
    return null;
  }

  public static boolean isExternalStorageDocument(Uri uri) {
    return "".equals(());
  }

  public static boolean isDownloadsDocument(Uri uri) {
    return "".equals(());
  }

  public static boolean isMediaDocument(Uri uri) {
    return "".equals(());
  }
}

References:/questions/42508383/illegalargumentexception-column-data-does-not-exist

Another article was found, personally tested, Android 4.4 to Android 10 is available, and the systems tested include VIVO, OPPO, MIUI, EMUI...

The problem of domestic manufacturers solved: Huawei's yellow icon manager, it returned to the standard Uri of 4.4, not the standard Uri of 4.4 or above. As a result, when parsing, it was judged to version > 4.4, and then used the standard parsing of 4.4 or above, and then failed, not without callbacks.

Directly available code snippets:

public class FileUtils {
 
  private Context context;
 
  public FileUtils(Context context) {
     = context;
  }
 
  public String getFilePathByUri(Uri uri) {
    // Start with file://    if (ContentResolver.SCHEME_FILE.equals(())) {
      return ();
    }
    // Those starting with /storage will also return directly    if (isOtherDocument(uri)) {
      return ();
    }
    // version compatible get!    String path = getFilePathByUri_BELOWAPI11(uri);
    if (path != null) {
      ("getFilePathByUri_BELOWAPI11 gets the path:" + path);
      return path;
    }
    path = getFilePathByUri_API11to18(uri);
    if (path != null) {
      ("getFilePathByUri_API11to18 gets the path:" + path);
      return path;
    }
    path = getFilePathByUri_API19(uri);
    ("The path obtained by getFilePathByUri_API19 is:" + path);
    return path;
  }
 
  private String getFilePathByUri_BELOWAPI11(Uri uri) {
    // Start with content://, for example, content://media/extenral/images/media/17766    if (ContentResolver.SCHEME_CONTENT.equals(())) {
      String path = null;
      String[] projection = new String[]{};
      Cursor cursor = ().query(uri, projection, null, null, null);
      if (cursor != null) {
        if (()) {
          int columnIndex = ();
          if (columnIndex > -1) {
            path = (columnIndex);
          }
        }
        ();
      }
      return path;
    }
    return null;
  }
 
  private String getFilePathByUri_API11to18(Uri contentUri) {
    String[] projection = {};
    String result = null;
    CursorLoader cursorLoader = new CursorLoader(context, contentUri, projection, null, null, null);
    Cursor cursor = ();
    if (cursor != null) {
      int column_index = ();
      ();
      result = (column_index);
      ();
    }
    return result;
  }
 
  private String getFilePathByUri_API19(Uri uri) {
    // 4.4 and later start with content://, for example, content:///document/image%3A235700    if (ContentResolver.SCHEME_CONTENT.equals(()) && .SDK_INT >= Build.VERSION_CODES.KITKAT) {
      if ((context, uri)) {
        if (isExternalStorageDocument(uri)) {
          // ExternalStorageProvider
          String docId = (uri);
          String[] split = (":");
          String type = split[0];
          if ("primary".equalsIgnoreCase(type)) {
            if ( > 1) {
              return () + "/" + split[1];
            } else {
              return () + "/";
            }
            // This is for checking SD Card
          }
        } else if (isDownloadsDocument(uri)) {
          //When downloading content provider, you should determine whether the download manager is disabled          int stateCode = ().getApplicationEnabledSetting("");
          if (stateCode != 0 && stateCode != 1) {
            return null;
          }
          String id = (uri);
          // If this RAW address appears, we can return directly!          if (("raw:")) {
            return ("raw:", "");
          }
          if ((":")) {
            String[] tmp = (":");
            if ( > 1) {
              id = tmp[1];
            }
          }
          Uri contentUri = ("content://downloads/public_downloads");
          ("Test Print Uri: " + uri);
          try {
            contentUri = (contentUri, (id));
          } catch (Exception e) {
            ();
          }
          String path = getDataColumn(contentUri, null, null);
          if (path != null) return path;
          // Compatible with file managers in certain special cases!          String fileName = getFileNameByUri(uri);
          if (fileName != null) {
            path = ().toString() + "/Download/" + fileName;
            return path;
          }
        } else if (isMediaDocument(uri)) {
          // MediaProvider
          String docId = (uri);
          String[] split = (":");
          String type = split[0];
          Uri contentUri = null;
          if ("image".equals(type)) {
            contentUri = .EXTERNAL_CONTENT_URI;
          } else if ("video".equals(type)) {
            contentUri = .EXTERNAL_CONTENT_URI;
          } else if ("audio".equals(type)) {
            contentUri = .EXTERNAL_CONTENT_URI;
          }
          String selection = "_id=?";
          String[] selectionArgs = new String[]{split[1]};
          return getDataColumn(contentUri, selection, selectionArgs);
        }
      }
    }
    return null;
  }
 
  private String getFileNameByUri(Uri uri) {
    String relativePath = getFileRelativePathByUri_API18(uri);
    if (relativePath == null) relativePath = "";
    final String[] projection = {
        .DISPLAY_NAME
    };
    try (Cursor cursor = ().query(uri, projection, null, null, null)) {
      if (cursor != null && ()) {
        int index = (.DISPLAY_NAME);
        return relativePath + (index);
      }
    }
    return null;
  }
 
  private String getFileRelativePathByUri_API18(Uri uri) {
    final String[] projection;
    if (.SDK_INT >= .VERSION_CODES.Q) {
      projection = new String[]{
          .RELATIVE_PATH
      };
      try (Cursor cursor = ().query(uri, projection, null, null, null)) {
        if (cursor != null && ()) {
          int index = (.RELATIVE_PATH);
          return (index);
        }
      }
    }
    return null;
  }
 
  private String getDataColumn(Uri uri, String selection, String[] selectionArgs) {
    final String column = ;
    final String[] projection = {column};
    try (Cursor cursor = ().query(uri, projection, selection, selectionArgs, null)) {
      if (cursor != null && ()) {
        final int column_index = (column);
        return (column_index);
      }
    } catch (IllegalArgumentException iae) {
      ();
    }
    return null;
  }
 
  private boolean isExternalStorageDocument(Uri uri) {
    return "".equals(());
  }
 
  private boolean isOtherDocument(Uri uri) {
    // Those starting with /storage will also return directly    if (uri != null && () != null) {
      String path = ();
      if (("/storage")) {
        return true;
      }
      if (("/external_files")) {
        return true;
      }
    }
    return false;
  }
 
  private boolean isDownloadsDocument(Uri uri) {
    return "".equals(());
  }
 
  private boolean isMediaDocument(Uri uri) {
    return "".equals(());
  }
}

Call getFilePathByUri(Uri uri) to get the final path.

This is the end of this article about the method implementation of Uri to paths above Android 7.0 (verified). For more information about Android 7 Uri to paths, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!