Get file path from URI

前端 未结 8 1082
你的背包
你的背包 2020-12-03 01:54

I have Uri for Image file.

I use this code for gets file path from Uri:

public String getRealPathFromURI(Uri contentUri) {
    Cursor cursor = null;
         


        
相关标签:
8条回答
  • 2020-12-03 02:33

    Solution:

        public class RealPathUtil {
    
        @SuppressLint("NewApi")
        public static String getRealPathFromURI_API19(Context context, Uri uri){
            String filePath = "";
            String wholeID = DocumentsContract.getDocumentId(uri);
    
             // Split at colon, use second item in the array
             String id = wholeID.split(":")[1];
    
             String[] column = { MediaStore.Images.Media.DATA };     
    
             // where id is equal to             
             String sel = MediaStore.Images.Media._ID + "=?";
    
             Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
                                       column, sel, new String[]{ id }, null);
    
             int columnIndex = cursor.getColumnIndex(column[0]);
    
             if (cursor.moveToFirst()) {
                 filePath = cursor.getString(columnIndex);
             }   
             cursor.close();
             return filePath;
        }
    
    
        @SuppressLint("NewApi")
        public static String getRealPathFromURI_API11to18(Context context, Uri contentUri) {
              String[] proj = { MediaStore.Images.Media.DATA };
              String result = null;
    
              CursorLoader cursorLoader = new CursorLoader(
                      context, 
                contentUri, proj, null, null, null);        
              Cursor cursor = cursorLoader.loadInBackground();
    
              if(cursor != null){
               int column_index = 
                 cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
               cursor.moveToFirst();
               result = cursor.getString(column_index);
              }
              return result;  
        }
    
        public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri){
                   String[] proj = { MediaStore.Images.Media.DATA };
                   Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
                   int column_index
              = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                   cursor.moveToFirst();
                   return cursor.getString(column_index);
        }
    }
    

    http://hmkcode.com/android-display-selected-image-and-its-real-path/

    0 讨论(0)
  • 2020-12-03 02:34

    Here's my solution, using all tricks I've found so far, which I use on my own app too (here) :

    FileUtilEx.kt

    fun Closeable?.closeSilently() {
        if (this != null) try {
            this.close()
        } catch (e: Exception) {
        }
    }
    
    object FileUtilEx {
        fun getFilePathFromUri(context: Context, uri: Uri, includeUriMappingTechnique: Boolean = true, tryToGetWritePermission: Boolean = false): ClosableFileHolder? {
            var file: File
            uri.path?.let {
                file = File(it)
                if (file.exists() && file.canRead()) {
    //                Log.d("AppLog", "got real file")
                    return ClosableFileHolder(file)
                }
            }
            if (uri.scheme == "file") {
                try {
                    val jUri = java.net.URI(uri.scheme, uri.schemeSpecificPart, uri.fragment)
                    file = File(jUri)
                    if (file.exists() && file.canRead()) {
    //                    Log.d("AppLog", "got real file")
                        return ClosableFileHolder(file)
                    }
                } catch (e: Exception) {
                }
                try {
                    val uriStr = uri.toString()
                    val decodePath = URLDecoder.decode(uriStr, "UTF-8")
                    file = File(decodePath)
                    if (file.exists() && file.canRead()) {
    //                    Log.d("AppLog", "got real file")
                        return ClosableFileHolder(file)
                    }
                } catch (e: UnsupportedEncodingException) {
                }
            }
            val authority = uri.authority
            if (uri.scheme == "content") {
                //handles "Files" app, and many others
                getRealPathFromUri(context, uri)?.let {
                    file = File(it)
                    if (file.exists() && file.canRead()) {
    //                    Log.d("AppLog", "got real file")
                        return ClosableFileHolder(file)
                    }
                }
            }
            if (includeUriMappingTechnique) {
                val fileUsingUriMappingTechnique = getFileUsingUriMappingTechnique(context, uri, tryToGetWritePermission)
                if (fileUsingUriMappingTechnique != null)
                    return fileUsingUriMappingTechnique
            }
            getFilePathFromDocumentUri(context, uri)?.let { filePath ->
                file = File(filePath)
                if (file.exists() && file.canRead())
                    return ClosableFileHolder(file)
            }
            return null
        }
    
    
        private fun getRealPathFromUri(context: Context, contentUri: Uri): String? {
            try {
                context.contentResolver.query(contentUri, arrayOf(MediaStore.Images.Media.DATA), null, null, null)?.use { cursor ->
                    val columnIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
                    if (columnIndex < 0 || cursor.count <= 0)
                        return null
                    cursor.moveToFirst()
                    return cursor.getString(columnIndex)
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return null
        }
    
        fun getFileUsingUriMappingTechnique(context: Context, androidUri: Uri, tryToGetWritePermission: Boolean = false): ClosableFileHolder? {
            var parcelFileDescriptor: ParcelFileDescriptor? = null
            for (i in 0..1)
                try {
                    parcelFileDescriptor = context.contentResolver.openFileDescriptor(androidUri, if (tryToGetWritePermission && i == 0) "w" else "r")
                    if (parcelFileDescriptor != null) {
                        val fd: Int = parcelFileDescriptor.fd
                        val linkFileName = "/proc/self/fd/$fd"
                        if (VERSION.SDK_INT >= VERSION_CODES.O) {
                            val realFilePath = Files.readSymbolicLink(Paths.get(linkFileName))
                            val file = realFilePath.toFile()
                            if (file.exists() && file.canRead()) {
                                parcelFileDescriptor.closeSilently()
                                return ClosableFileHolder(file)
                            }
                        }
                        val file = File(linkFileName)
                        if (file.exists() && file.canRead())
                            return ClosableFileHolder(file, parcelFileDescriptor)
                        parcelFileDescriptor.closeSilently()
                    }
                } catch (e: Exception) {
                    parcelFileDescriptor.closeSilently()
                    parcelFileDescriptor = null
                }
            return null
        }
    
        private fun getFilePathFromDocumentUri(context: Context, uri: Uri): String? {
            //            https://stackoverflow.com/questions/5657411/android-getting-a-file-uri-from-a-content-uri
            // DocumentProvider
            if (VERSION.SDK_INT >= VERSION_CODES.KITKAT && DocumentFile.isDocumentUri(context, uri)) {
                // ExternalStorageProvider
                if ("com.android.externalstorage.documents" == uri.authority) {
                    val docId = DocumentsContract.getDocumentId(uri)
                    val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                    val type = split[0]
                    // This is for checking Main Memory
                    return if ("primary".equals(type, ignoreCase = true)) {
                        if (split.size > 1) {
                            Environment.getExternalStorageDirectory().absolutePath + "/" + split[1] + "/"
                        } else {
                            Environment.getExternalStorageDirectory().absolutePath + "/"
                        }
                        // This is for checking SD Card
                    } else {
                        "storage" + "/" + docId.replace(":", "/")
                    }
                }
            }
            return null
        }
    }
    

    ClosableFileHolder.kt

    class ClosableFileHolder(val file: File, private val parcelFileDescriptor: ParcelFileDescriptor? = null) : Closeable {
    
        fun isUsingUriMappingTechnique(): Boolean = parcelFileDescriptor != null
    
        override fun close() {
            parcelFileDescriptor.closeSilently()
        }
    
        protected fun finalize() {
            parcelFileDescriptor.closeSilently()
        }
    }
    
    

    Usage:

    FileUtilEx.getFilePathFromUri(context, uri, false)?.use {
        val file = it.file
        ...
    }
    

    The tryToGetWritePermission parameter is in case you want to access the file, but it's in fact not available normally (like in SAF), so it's offered you in a different place. This is useful in case you want to access the file but don't care where it really exists.

    0 讨论(0)
  • 2020-12-03 02:37

    I think this should work. A generalized code for getting URI from path :

    String path = yourAndroidURI.uri.getPath()
    File file = new File(new URI(path));
    
    0 讨论(0)
  • 2020-12-03 02:38

    Check following link is the best solution http://kaushalprajapati.net/mobile/android/android-get-the-full-file-path-from-uri/

    0 讨论(0)
  • 2020-12-03 02:39

    So I tried basically ever answer on the stack but this was the only one that worked for me. It is important to think about the uri as a "promise" that an image lives where it points to. This does not mean there is a file at that location but if you ask correctly you will get an image. attachementPath is the path to the image (can be used like a regular file). See below:

    try {
                InputStream input = getActivity().getContentResolver().openInputStream(imageUri);
                File file = new File(getActivity().getCacheDir(), "cacheFileAppeal.png");
                try {
    
                    OutputStream output = new FileOutputStream(file);
                    try {
                        try {
                            byte[] buffer = new byte[4 * 1024]; // or other buffer size
                            int read;
    
                            if (input != null) {
                                while ((read = input.read(buffer)) != -1) {
                                    output.write(buffer, 0, read);
                                }
                            }
                            output.flush();
                        } finally {
                            output.close();
                            attachmentPath = file.getAbsolutePath();
                        }
                    } catch (Exception e) {
                        e.printStackTrace(); // handle exception, define IOException and others
                    }
    
                } finally {
                    try {
                        if (input != null) {
                            input.close();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
    
    0 讨论(0)
  • 2020-12-03 02:42

    Make sure you give permission in Manifest. Wasted 2 hours trying various methods without giving permissions :/

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
    0 讨论(0)
提交回复
热议问题