How to get the file path from uri in Android devices having Oreo and above OS

前端 未结 3 1395
长发绾君心
长发绾君心 2021-01-16 21:34

To select an audio file using Intent , I am using this function :-

fun selectAudioFromStorage() {
    val pictureActionIntent = Intent(Intent.ACTION_GET_CONT         


        
相关标签:
3条回答
  • 2021-01-16 22:12

    As file paths are not usable in API 29 and above for public files I suggest that you don't try to use them but use a Java FileDescriptor instead.

    As per https://developer.android.com/training/data-storage#scoped-storage

    And more specifically https://developer.android.com/training/data-storage/shared/media#open-file-descriptor

    A lot of API's allow you to provide a FileDescriptor instead of a path.

    e.g. Use https://developer.android.com/reference/android/media/MediaPlayer.html#setDataSource(java.io.FileDescriptor)

    instead of

    https://developer.android.com/reference/android/media/MediaPlayer.html#setDataSource(java.lang.String)

    To get a fileDescriptor from a URI do the following (in Java)

    
    ParcelFileDescriptor pfd =
                    this.getContentResolver().
                            openFileDescriptor(URI, "r");
    
    FileDescriptor fileDescriptor = pfd.getFileDescriptor();
    
    
    0 讨论(0)
  • 2021-01-16 22:19

    I solved it. Simply call this getPathFromURI method and it will return the file path

    object RealPathHelper {
    
    private const val BUFFER_SIZE = 1024 * 2
    
    
    @TargetApi(Build.VERSION_CODES.O)
    fun getPathFromURI(
        context: Context,
        contentUri: Uri,
        fileNamePrefix: String,
        defaultFileExtension: String
    ): String? {
        val uriPath: String = contentUri.path ?: return null
        val fileName: String = MediaFileHelper.getFileNameWithExtension(uriPath)
    
        if (fileName.isNotBlank()) {
            val destFile =
                createOutputFile(context, contentUri, fileNamePrefix, defaultFileExtension)
            copyUriToFile(context, contentUri, destFile)
            return destFile.absolutePath
        }
        return null
    }
    
    private fun createOutputFile(
        context: Context,
        contentUri: Uri,
        fileNamePrefix: String,
        defaultFileExtension: String
    ): File {
        var count = 0
        var file: File
    
        val uriPath: String? = contentUri.path
        val fileExtension = if (uriPath == null) defaultFileExtension
        else MediaFileHelper.getFileExtension(uriPath)
    
        do {
            count++
    
            val mFileName = "$fileNamePrefix${StringHelper.getUniqueId()}$count$fileExtension"
            val newFilePath =
                "${context.getExternalFilesDir(null)?.absolutePath}${context.getString(R.string.audio_select_directory)}/$mFileName"
    
            file = File(newFilePath)
    
        } while (file.exists() && !file.isDirectory)
    
        return file
    }
    
    private fun copyUriToFile(context: Context, srcUri: Uri, dstFile: File) {
        try {
            val inputStream = context.contentResolver.openInputStream(srcUri) ?: return
            val outputStream = FileOutputStream(dstFile)
            inputStream.copyTo(outputStream, BUFFER_SIZE)
            inputStream.close()
            outputStream.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }
    
    0 讨论(0)
  • 2021-01-16 22:29

    I usually use this Class for getting the path,, You can have a look at this which works for almost all version

    public class RealPathUtil {
    
        public static String getRealPath(Context context, Uri fileUri) {
            String realPath;
            // SDK < API11
            if (Build.VERSION.SDK_INT < 11) {
                realPath = RealPathUtil.getRealPathFromURI_BelowAPI11(context, fileUri);
            }
            // SDK >= 11 && SDK < 19
            else if (Build.VERSION.SDK_INT < 19) {
                realPath = RealPathUtil.getRealPathFromURI_API11to18(context, fileUri);
            }
            // SDK > 19 (Android 4.4) and up
            else {
                realPath = RealPathUtil.getRealPathFromURI_API19(context, fileUri);
            }
            return realPath;
        }
    
    
        @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);
                cursor.close();
            }
            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 = 0;
            String result = "";
            if (cursor != null) {
                column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                result = cursor.getString(column_index);
                cursor.close();
                return result;
            }
            return result;
        }
    
        /**
         * Get a file path from a Uri. This will get the the path for Storage Access
         * Framework Documents, as well as the _data field for the MediaStore and
         * other file-based ContentProviders.
         *
         * @param context The context.
         * @param uri     The Uri to query.
         * @author paulburke
         */
        @SuppressLint("NewApi")
        public static String getRealPathFromURI_API19(final Context context, final Uri uri) {
    
            final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    
            // DocumentProvider
            if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
                // ExternalStorageProvider
                if (isExternalStorageDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];
    
                    if ("primary".equalsIgnoreCase(type)) {
                        return Environment.getExternalStorageDirectory() + "/" + split[1];
                    }
    
                    // TODO handle non-primary volumes
                }
                // DownloadsProvider
                else if (isDownloadsDocument(uri)) {
    
                    final String id = DocumentsContract.getDocumentId(uri);
                    final Uri contentUri = ContentUris.withAppendedId(
                            Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
    
                    return getDataColumn(context, contentUri, null, null);
                }
                // MediaProvider
                else if (isMediaDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];
    
                    Uri contentUri = null;
                    if ("image".equals(type)) {
                        contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    } else if ("video".equals(type)) {
                        contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                    } else if ("audio".equals(type)) {
                        contentUri = MediaStore.Audio.Media.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(uri.getScheme())) {
    
                // Return the remote address
                if (isGooglePhotosUri(uri))
                    return uri.getLastPathSegment();
    
                return getDataColumn(context, uri, null, null);
            }
            // File
            else if ("file".equalsIgnoreCase(uri.getScheme())) {
                return uri.getPath();
            }
    
            return null;
        }
    
        /**
         * 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.
         * @param selection     (Optional) Filter used in the query.
         * @param selectionArgs (Optional) Selection arguments used in the query.
         * @return The value of the _data column, which is typically a file path.
         */
        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;
        }
    
    
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is ExternalStorageProvider.
         */
        public static boolean isExternalStorageDocument(Uri uri) {
            return "com.android.externalstorage.documents".equals(uri.getAuthority());
        }
    
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is DownloadsProvider.
         */
        public static boolean isDownloadsDocument(Uri uri) {
            return "com.android.providers.downloads.documents".equals(uri.getAuthority());
        }
    
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is MediaProvider.
         */
        public static boolean isMediaDocument(Uri uri) {
            return "com.android.providers.media.documents".equals(uri.getAuthority());
        }
    
        /**
         * @param uri The Uri to check.
         * @return Whether the Uri authority is Google Photos.
         */
        public static boolean isGooglePhotosUri(Uri uri) {
            return "com.google.android.apps.photos.content".equals(uri.getAuthority());
        }
    
    }
    

    Reference: https://gist.github.com/tatocaster/32aad15f6e0c50311626

    0 讨论(0)
提交回复
热议问题