代码之家  ›  专栏  ›  技术社区  ›  stealthcopter

从mediastore的uri获取文件名和路径

  •  353
  • stealthcopter  · 技术社区  · 14 年前

    我有一个 onActivityResult 从MediaStore图像选择返回,我可以使用以下方法获取图像的URI:

    Uri selectedImage = data.getData();
    

    将其转换为字符串将得到:

    content://media/external/images/media/47
    

    或者给一条路径:

    /external/images/media/47
    

    然而,我似乎找不到一种方法将其转换为绝对路径,因为我想将图像加载到位图中而不必将其复制到某个位置。我知道这可以通过使用URI和内容解析器来完成,但我想这似乎在重新启动手机时中断了。 MediaStore 在重新启动之间不保持相同的编号。

    23 回复  |  直到 5 年前
        1
  •  593
  •   Sheikh Hasib    6 年前

    API 19以下 使用此代码从URI获取文件路径:

    public String getRealPathFromURI(Context context, Uri contentUri) {
      Cursor cursor = null;
      try { 
        String[] proj = { MediaStore.Images.Media.DATA };
        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);
      } finally {
        if (cursor != null) {
          cursor.close();
        }
      }
    }
    
        2
  •  118
  •   Sebastiano    9 年前

    只是第一个答案的简单更新: mActivity.managedQuery() 现已弃用。我用新方法更新了代码。

    private String getRealPathFromURI(Uri contentUri) {
        String[] proj = { MediaStore.Images.Media.DATA };
        CursorLoader loader = new CursorLoader(mContext, contentUri, proj, null, null, null);
        Cursor cursor = loader.loadInBackground();
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String result = cursor.getString(column_index);
        cursor.close();
        return result;
    }
    

    android dev source

        3
  •  93
  •   mig    13 年前

    不要试图在文件系统中找到一个URI,这样在数据库中查找东西很慢。

    通过向工厂提供输入流,可以从URI获取位图,就像向工厂提供文件一样:

    InputStream is = getContentResolver().openInputStream(uri);
    Bitmap bitmap = BitmapFactory.decodeStream(is);
    is.close();
    
        4
  •  91
  •   Jitendra    5 年前

    奥利奥

    Uri uri = data.getData(); 
    File file = new File(uri.getPath());//create path from uri
    final String[] split = file.getPath().split(":");//split the path.
    filePath = split[1];//assign it to a string(your choice).
    

    对于以下所有版本的oreo,我都使用这个方法从uri中获取实际路径

     @SuppressLint("NewApi")
        public static String getFilePath(Context context, Uri uri) throws URISyntaxException {
            String selection = null;
            String[] selectionArgs = null;
            // Uri is different in versions after KITKAT (Android 4.4), we need to
            if (Build.VERSION.SDK_INT >= 19 && DocumentsContract.isDocumentUri(context.getApplicationContext(), uri)) {
                if (isExternalStorageDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                } else if (isDownloadsDocument(uri)) {
                    final String id = DocumentsContract.getDocumentId(uri);
                    uri = ContentUris.withAppendedId(
                            Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                } else if (isMediaDocument(uri)) {
                    final String docId = DocumentsContract.getDocumentId(uri);
                    final String[] split = docId.split(":");
                    final String type = split[0];
                    if ("image".equals(type)) {
                        uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                    } else if ("video".equals(type)) {
                        uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                    } else if ("audio".equals(type)) {
                        uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                    }
                    selection = "_id=?";
                    selectionArgs = new String[]{
                            split[1]
                    };
                }
            }
            if ("content".equalsIgnoreCase(uri.getScheme())) {
    
    
              if (isGooglePhotosUri(uri)) {
                  return uri.getLastPathSegment();
               }
    
                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) {
                }
            } else if ("file".equalsIgnoreCase(uri.getScheme())) {
                return uri.getPath();
            }
            return null;
        }
    
        public static boolean isExternalStorageDocument(Uri uri) {
            return "com.android.externalstorage.documents".equals(uri.getAuthority());
        }
    
        public static boolean isDownloadsDocument(Uri uri) {
            return "com.android.providers.downloads.documents".equals(uri.getAuthority());
        }
    
        public static boolean isMediaDocument(Uri uri) {
            return "com.android.providers.media.documents".equals(uri.getAuthority());
        }
    
      public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }
    
        5
  •  39
  •   Romain Piel    11 年前

    这里是我获取文件名的示例,从类似于uri的文件:/…内容://…它不仅适用于Android MediaStore,也适用于ezexplorer等第三方应用程序。

    public static String getFileNameByUri(Context context, Uri uri)
    {
        String fileName="unknown";//default fileName
        Uri filePathUri = uri;
        if (uri.getScheme().toString().compareTo("content")==0)
        {      
            Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
            if (cursor.moveToFirst())
            {
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data"
                filePathUri = Uri.parse(cursor.getString(column_index));
                fileName = filePathUri.getLastPathSegment().toString();
            }
        }
        else if (uri.getScheme().compareTo("file")==0)
        {
            fileName = filePathUri.getLastPathSegment().toString();
        }
        else
        {
            fileName = fileName+"_"+filePathUri.getLastPathSegment();
        }
        return fileName;
    }
    
        6
  •  15
  •   Jon O    12 年前

    很好的现有答案,其中一些我曾经提出过自己的答案:

    我必须从uris中获取路径,从路径中获取uri,而google很难区分这一点,因此对于任何有相同问题的人(例如,从 MediaStore 一段视频的物理位置)。前者:

    /**
     * Gets the corresponding path to a file from the given content:// URI
     * @param selectedVideoUri The content:// URI to find the file path from
     * @param contentResolver The content resolver to use to perform the query.
     * @return the file path as a string
     */
    private String getFilePathFromContentUri(Uri selectedVideoUri,
            ContentResolver contentResolver) {
        String filePath;
        String[] filePathColumn = {MediaColumns.DATA};
    
        Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
        cursor.moveToFirst();
    
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        filePath = cursor.getString(columnIndex);
        cursor.close();
        return filePath;
    }
    

    后者(我用于视频,但也可用于音频或文件或其他类型的存储内容,方法是用mediastore.audio(etc)替换mediastore.video):

    /**
     * Gets the MediaStore video ID of a given file on external storage
     * @param filePath The path (on external storage) of the file to resolve the ID of
     * @param contentResolver The content resolver to use to perform the query.
     * @return the video ID as a long
     */
    private long getVideoIdFromFilePath(String filePath,
            ContentResolver contentResolver) {
    
    
        long videoId;
        Log.d(TAG,"Loading file " + filePath);
    
                // This returns us content://media/external/videos/media (or something like that)
                // I pass in "external" because that's the MediaStore's name for the external
                // storage on my device (the other possibility is "internal")
        Uri videosUri = MediaStore.Video.Media.getContentUri("external");
    
        Log.d(TAG,"videosUri = " + videosUri.toString());
    
        String[] projection = {MediaStore.Video.VideoColumns._ID};
    
        // TODO This will break if we have no matching item in the MediaStore.
        Cursor cursor = contentResolver.query(videosUri, projection, MediaStore.Video.VideoColumns.DATA + " LIKE ?", new String[] { filePath }, null);
        cursor.moveToFirst();
    
        int columnIndex = cursor.getColumnIndex(projection[0]);
        videoId = cursor.getLong(columnIndex);
    
        Log.d(TAG,"Video ID is " + videoId);
        cursor.close();
        return videoId;
    }
    

    基本上, DATA 纵横 (或者您查询的其中任何一个子节)存储文件路径,因此您可以使用您知道的内容来查找该路径。 数据 字段,或者使用该字段查找您需要的其他内容。

    然后我进一步使用 Scheme 如上所述,了解如何处理我的数据:

     private boolean  getSelectedVideo(Intent imageReturnedIntent, boolean fromData) {
    
        Uri selectedVideoUri;
    
        //Selected image returned from another activity
                // A parameter I pass myself to know whether or not I'm being "shared via" or
                // whether I'm working internally to my app (fromData = working internally)
        if(fromData){
            selectedVideoUri = imageReturnedIntent.getData();
        } else {
            //Selected image returned from SEND intent 
                        // which I register to receive in my manifest
                        // (so people can "share via" my app)
            selectedVideoUri = (Uri)getIntent().getExtras().get(Intent.EXTRA_STREAM);
        }
    
        Log.d(TAG,"SelectedVideoUri = " + selectedVideoUri);
    
        String filePath;
    
        String scheme = selectedVideoUri.getScheme(); 
        ContentResolver contentResolver = getContentResolver();
        long videoId;
    
        // If we are sent file://something or content://org.openintents.filemanager/mimetype/something...
        if(scheme.equals("file") || (scheme.equals("content") && selectedVideoUri.getEncodedAuthority().equals("org.openintents.filemanager"))){
    
            // Get the path
            filePath = selectedVideoUri.getPath();
    
            // Trim the path if necessary
            // openintents filemanager returns content://org.openintents.filemanager/mimetype//mnt/sdcard/xxxx.mp4
            if(filePath.startsWith("/mimetype/")){
                String trimmedFilePath = filePath.substring("/mimetype/".length());
                filePath = trimmedFilePath.substring(trimmedFilePath.indexOf("/"));
            }
    
            // Get the video ID from the path
            videoId = getVideoIdFromFilePath(filePath, contentResolver);
    
        } else if(scheme.equals("content")){
    
            // If we are given another content:// URI, look it up in the media provider
            videoId = Long.valueOf(selectedVideoUri.getLastPathSegment());
            filePath = getFilePathFromContentUri(selectedVideoUri, contentResolver);
    
        } else {
            Log.d(TAG,"Failed to load URI " + selectedVideoUri.toString());
            return false;
        }
    
         return true;
     }
    
        7
  •  10
  •   YYamil    8 年前

    所有这些答案对我都不起作用。我必须直接去谷歌的文档 https://developer.android.com/guide/topics/providers/document-provider.html 在这个主题上,找到了这个有用的方法:

    private Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
        getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
    }
    

    您可以使用此位图在图像视图中显示它。

        8
  •  4
  •   Shiv Kumar    7 年前

    尝试从uri获取图像文件路径

    public void getImageFilePath(Context context, Uri uri) {
    
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        cursor.moveToFirst();
        String image_id = cursor.getString(0);
        image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
        cursor.close();
        cursor = context.getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
        cursor.moveToFirst();
        String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();
        upLoadImageOrLogo(path);
    }
    
        9
  •  3
  •   Community Romance    7 年前

    对于那些搬到Kitkat后有问题的人的解决方案:

    这将从mediaprovider、downloadsprovider和externalstorageprovider获取文件路径,同时返回到非官方的contentprovider方法。 https://stackoverflow.com/a/20559175/690777

        10
  •  3
  •   Peter Mortensen Mohit    8 年前

    从库中获取图像后,只需在下面的方法中为 Android 4.4 (KITKAT):

    public String getPath(Uri contentUri) {// Will return "image:x*"
    
        String wholeID = DocumentsContract.getDocumentId(contentUri);
    
        // 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 = getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel,
                new String[] { id }, null);
    
        String filePath = "";
    
        int columnIndex = cursor.getColumnIndex(column[0]);
    
        if (cursor.moveToFirst()) {
            filePath = cursor.getString(columnIndex);
        }
    
        cursor.close();
        return filePath;
    }
    
        11
  •  2
  •   Peter Mortensen Mohit    8 年前

    由于ManagedQuery已被弃用,您可以尝试:

    CursorLoader cursorLoader = new CursorLoader(context, uri, proj, null, null, null);
    Cursor cursor = cursorLoader.loadInBackground();
    
        12
  •  2
  •   Peter Mortensen Mohit    8 年前

    在这里,我将向您展示如何创建一个浏览按钮,当您单击该按钮时,它将打开SD卡,您将选择一个文件,因此您将获得所选文件的文件名和文件路径:

    你要点击的按钮

    browse.setOnClickListener(new OnClickListener()
    {
        public void onClick(View v)
        {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_PICK);
            Uri startDir = Uri.fromFile(new File("/sdcard"));
            startActivityForResult(intent, PICK_REQUEST_CODE);
        }
    });
    

    获取结果文件名和文件路径的函数

    protected void onActivityResult(int requestCode, int resultCode, Intent intent)
    {
        if (requestCode == PICK_REQUEST_CODE)
        {
            if (resultCode == RESULT_OK)
            {
                Uri uri = intent.getData();
    
                if (uri.getScheme().toString().compareTo("content")==0)
                {
                    Cursor cursor =getContentResolver().query(uri, null, null, null, null);
                    if (cursor.moveToFirst())
                    {
                        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data"
                        Uri filePathUri = Uri.parse(cursor.getString(column_index));
                        String file_name = filePathUri.getLastPathSegment().toString();
                        String file_path=filePathUri.getPath();
                        Toast.makeText(this,"File Name & PATH are:"+file_name+"\n"+file_path, Toast.LENGTH_LONG).show();
                    }
                }
            }
        }
    }
    
        13
  •  2
  •   Arst    7 年前

    此解决方案适用于所有情况:

    在某些情况下,从URL获取路径太难了。那你为什么需要这条路?把文件复制到其他地方?你不需要这条路。

    public void SavePhotoUri (Uri imageuri, String Filename){
    
        File FilePath = context.getDir(Environment.DIRECTORY_PICTURES,Context.MODE_PRIVATE);
        try {
            Bitmap selectedImage = MediaStore.Images.Media.getBitmap(context.getContentResolver(), imageuri);
            String destinationImagePath = FilePath + "/" + Filename;
            FileOutputStream destination = new FileOutputStream(destinationImagePath);
            selectedImage.compress(Bitmap.CompressFormat.JPEG, 100, destination);
            destination.close();
        }
        catch (Exception e) {
            Log.e("error", e.toString());
        }
    }
    
        14
  •  1
  •   sberezin    9 年前

    稍微修改过的@percypercy版本-它不会抛出 如果出错,返回空值 :

    public String getPathFromMediaUri(Context context, Uri uri) {
        String result = null;
    
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
        int col = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
        if (col >= 0 && cursor.moveToFirst())
            result = cursor.getString(col);
        cursor.close();
    
        return result;
    }
    
        15
  •  1
  •   Snow Flake    9 年前

    这是文件名

    String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
                        Uri uri = data.getData();
                        String fileName = null;
                        ContentResolver cr = getActivity().getApplicationContext().getContentResolver();
    
                        Cursor metaCursor = cr.query(uri,
                                projection, null, null, null);
                        if (metaCursor != null) {
                            try {
                                if (metaCursor.moveToFirst()) {
                                    fileName = metaCursor.getString(0);
                                }
                            } finally {
                                metaCursor.close();
                            }
                        }
    
        16
  •  1
  •   Peter Mortensen Mohit    8 年前

    简单而简单。您可以像下面那样从URI中执行此操作!

    public void getContents(Uri uri)
    {
        Cursor vidCursor = getActivity.getContentResolver().query(uri, null, null,
                                                                  null, null);
        if (vidCursor.moveToFirst())
        {
            int column_index =
            vidCursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            Uri filePathUri = Uri.parse(vidCursor .getString(column_index));
            String video_name =  filePathUri.getLastPathSegment().toString();
            String file_path=filePathUri.getPath();
            Log.i("TAG", video_name + "\b" file_path);
        }
    }
    
        17
  •  1
  •   Sunil    6 年前

    试试这个

    不过,如果你想找到问题的真正路径,你可以试试我的答案。以上答案对我没有帮助。

    解释 :-此方法获取URI,然后根据API级别检查Android设备的API级别,然后生成实际路径。 根据API级别,生成实路径方法的代码是不同的。

    1. 从URI获取实际路径的方法

      @SuppressLint("ObsoleteSdkInt")
      public String getPathFromURI(Uri uri){
          String realPath="";
      // SDK < API11
          if (Build.VERSION.SDK_INT < 11) {
              String[] proj = { MediaStore.Images.Media.DATA };
              @SuppressLint("Recycle") Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
              int column_index = 0;
              String result="";
              if (cursor != null) {
                  column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                  realPath=cursor.getString(column_index);
              }
          }
          // SDK >= 11 && SDK < 19
          else if (Build.VERSION.SDK_INT < 19){
              String[] proj = { MediaStore.Images.Media.DATA };
              CursorLoader cursorLoader = new CursorLoader(this, uri, proj, null, null, null);
              Cursor cursor = cursorLoader.loadInBackground();
              if(cursor != null){
                  int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                  cursor.moveToFirst();
                  realPath = cursor.getString(column_index);
              }
          }
          // SDK > 19 (Android 4.4)
          else{
              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 = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null);
              int columnIndex = 0;
              if (cursor != null) {
                  columnIndex = cursor.getColumnIndex(column[0]);
                  if (cursor.moveToFirst()) {
                      realPath = cursor.getString(columnIndex);
                  }
                  cursor.close();
              }
          }
          return realPath;
       }
      
    2. 像这样使用这个方法

      Log.e(TAG, "getRealPathFromURI: "+getPathFromURI(your_selected_uri) );
      

    输出:

    04-06 12:39:46.993 6138-6138/com.app.qtm e/tag:getrealpathfromuri: /存储/模拟/0/视频/复仇者无限战争4K 8K-7680x4320.jpg

        18
  •  1
  •   Sheikh Hasib    6 年前

    API 19及以上 , 来自URI的图像文件路径 工作得很好。我最近也查过这个 奥利奥API 27 .

    public String getImageFilePath(Uri uri) {
        String path = null, image_id = null;
    
        Cursor cursor = getContentResolver().query(uri, null, null, null, null);
        if (cursor != null) {
            cursor.moveToFirst();
            image_id = cursor.getString(0);
            image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
            cursor.close();
        }
    
        Cursor cursor = getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
        if (cursor!=null) {
            cursor.moveToFirst();
            path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
            cursor.close();
        }
        return path;
    }
    
        19
  •  1
  •   user7590744    6 年前

    我已经这样做了:

        Uri queryUri = MediaStore.Files.getContentUri("external");
        String columnData = MediaStore.Files.FileColumns.DATA;
        String columnSize = MediaStore.Files.FileColumns.SIZE;
    
        String[] projectionData = {MediaStore.Files.FileColumns.DATA};
    
    
        String name = null;
        String size = null;
    
        Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
        if ((cursor != null)&&(cursor.getCount()>0)) {
            int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
            int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
    
            cursor.moveToFirst();
    
            name = cursor.getString(nameIndex);
            size = cursor.getString(sizeIndex);
    
            cursor.close();
        }
    
        if ((name!=null)&&(size!=null)){
            String selectionNS = columnData + " LIKE '%" + name + "' AND " +columnSize + "='" + size +"'";
    
            Cursor cursorLike = getContentResolver().query(queryUri, projectionData, selectionNS, null, null);
    
            if ((cursorLike != null)&&(cursorLike.getCount()>0)) {
                cursorLike.moveToFirst();
                int indexData = cursorLike.getColumnIndex(columnData);
                if (cursorLike.getString(indexData) != null) {
                    result = cursorLike.getString(indexData);
                }
                cursorLike.close();
            }
        }
    
        return result;
    
        20
  •  0
  •   Serg Burlaka    6 年前

    很好地为我修复了这个代码 post :

      public static String getRealPathImageFromUri(Uri uri) {
            String fileName =null;
            if (uri.getScheme().equals("content")) {
                try (Cursor cursor = MyApplication.getInstance().getContentResolver().query(uri, null, null, null, null)) {
                    if (cursor.moveToFirst()) {
                        fileName = cursor.getString(cursor.getColumnIndexOrThrow(ediaStore.Images.Media.DATA));
                    }
                } catch (IllegalArgumentException e) {
                    Log.e(mTag, "Get path failed", e);
                }
            }
            return fileName;
        }
    
        21
  •  0
  •   johnml1135    6 年前

    作为一个附加组件,如果在尝试打开输入流之前需要查看文件是否存在,则可以使用documentscotract。

    (Kotlin密码)

    var iStream = null
    if(DocumentsContract.isDocumentUri(context,myUri)) {
       val pfd: ParcelFileDescriptor? = context.contentResolver.openFileDescriptor(
                myUri, "r") ?: return null
       iStream = ParcelFileDescriptor.AutoCloseInputStream(pfd)
    }
    
        22
  •  0
  •   Harshil Pansare    6 年前

    由于上述答案对我不起作用,以下是对我起作用的解决方案:

    对于19级和19级API。

    此方法涵盖从URI获取文件路径的所有情况

    /**
     * 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 activity.
     * @param uri The Uri to query.
     * @author paulburke
     */
    public static String getPath(final Context context, final Uri uri) {
    
        // DocumentProvider
        if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && 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];
                }else{
                    Toast.makeText(context, "Could not get file path. Please try again", Toast.LENGTH_SHORT).show();
                }
            }
            // 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;
                } else {
                    contentUri = MediaStore.Files.getContentUri("external");
                }
    
                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 getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
    
        return null;
    }
    
        23
  •  -2
  •   Drastaro    8 年前

    Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);