Android获取图库图片Uri路径

Posted

技术标签:

【中文标题】Android获取图库图片Uri路径【英文标题】:Android get Gallery image Uri path 【发布时间】:2011-10-19 14:44:03 【问题描述】:

在 Activity 中,我可以从 Gallery 中选择一张图片,我需要它的 Uri 路径(在日志中,我的测试图片的 Uri 路径是 /content:/media/external/images/media/1)。

我收到了这个错误:

08-04 02:14:21.912: DEBUG/PHOTOUPLOADER(576): java.io.FileNotFoundException: /content:/media/external/images/media/1 (No such file or directory)
08-04 02:14:32.124: WARN/System.err(576): java.io.FileNotFoundException: /content:/media/external/images/media/1 (No such file or directory)

这是正确的文件路径格式吗?或者我应该把它变成sdcard\...\image.png之类的东西?

【问题讨论】:

致任何可能也有此问题的人:您确实需要文件的绝对路径。我将发布上面的方法,您可以使用该方法将此 uri 转换为路径 如果您有解决方案,请将其发布为答案。 我的意思是,将其发布为答案。因为它回答了问题,所以其他人认为它已回答。 【参考方案1】:
public String getPath(Uri uri) 
    String[] projection =  MediaStore.Images.Media.DATA ;
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    startManagingCursor(cursor);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);

【讨论】:

对于其他到达这里的人,请注意 managedQuery 是一个活动的方法,因此您可能需要提供一个活动。 第二个注意是光标应该关闭cursor.close() 来自文档:警告:不要在使用此方法获得的游标上调用 Cursor.close(),因为活动会在适当的时候为您执行此操作。 我想提一下 managedQuery 现在已弃用。如果有人为 android API 4 及更高版本开发应用程序,请添加支持库 v4 并使用以下代码:CursorLoader loader = new CursorLoader(context, uri, projection, null, null, null); Cursor cursor = loader.loadInBackground(); 而不是 Cursor cursor = managedQuery(uri, projection, null, null, null); MediaStore.Images.Media.DATA 也已弃用,此方法将不再有效【参考方案2】:
val inputStream = context.contentResolver.openInputStream(uri)

就是你所需要的。

【讨论】:

这个答案怎么还没得到任何赞成票呢?这正是我们所需要的。谢谢楼主! 这太容易了。它是否仅适用于某些 SDK 版本或其他东西? @DavidKennedy ContentResolver#openInputStream() 是在 API 级别 1 中添加的,所以不要这么认为 很好,但是我如何从这个 InputStream 中获取路径? @whereismaxmax 你没有,想法是抽象出文件路径【参考方案3】:

这适用于所有 SDK 版本:

/**
 * 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
 */
public static String getPath(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());

取自这里:https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java

【讨论】:

这在奥利奥上失败了【参考方案4】:

试试

                 // open a URL connection to the Servlet
               FileInputStream fileInputStream = new FileInputStream(sourceFile);
               URL url = new URL(upLoadServerUri);

               // Open a HTTP  connection to  the URL
               conn = (HttpURLConnection) url.openConnection();
               conn.setDoInput(true); // Allow Inputs
               conn.setDoOutput(true); // Allow Outputs
               conn.setUseCaches(false); // Don't use a Cached Copy
               conn.setRequestMethod("POST");
               conn.setRequestProperty("Connection", "Keep-Alive");
               conn.setRequestProperty("ENCTYPE", "multipart/form-data");
               conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
               conn.setRequestProperty("uploaded_file", fileName);

               dos = new DataOutputStream(conn.getOutputStream());

               dos.writeBytes(twoHyphens + boundary + lineEnd);
               dos.writeBytes("Content-Disposition: form-data; name=uploaded_file;filename="+ fileName + "" + lineEnd);

               dos.writeBytes(lineEnd);

               // create a buffer of  maximum size
               bytesAvailable = fileInputStream.available();

               bufferSize = Math.min(bytesAvailable, maxBufferSize);
               buffer = new byte[bufferSize];

               // read file and write it into form...
               bytesRead = fileInputStream.read(buffer, 0, bufferSize); 

               while (bytesRead > 0) 

                 dos.write(buffer, 0, bufferSize);
                 bytesAvailable = fileInputStream.available();
                 bufferSize = Math.min(bytesAvailable, maxBufferSize);
                 bytesRead = fileInputStream.read(buffer, 0, bufferSize); 

                

               // send multipart form data necesssary after file data...
               dos.writeBytes(lineEnd);
               dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

               // Responses from the server (code and message)
               serverResponseCode = conn.getResponseCode();
               String serverResponseMessage = conn.getResponseMessage();

               Log.i("uploadFile", "HTTP Response is : "
                       + serverResponseMessage + ": " + serverResponseCode);

               if(serverResponseCode == 200)

                   runOnUiThread(new Runnable() 
                        public void run() 

                            String msg = "File Upload Completed.\n\n See uploaded file here : \n\n"
                                          +" http://www.androidtrainer.netne.net.com/uploads/"
                                          +uploadFileName;

                            messageText.setText(msg);
                            Toast.makeText(UploadToServer.this, "File Upload Complete.",
                                         Toast.LENGTH_SHORT).show();
                        
                    );               
                  

               //close the streams //
               fileInputStream.close();
               dos.flush();
               dos.close();

           catch (MalformedURLException ex) 

              dialog.dismiss(); 
              ex.printStackTrace();

              runOnUiThread(new Runnable() 
                  public void run() 
                      messageText.setText("MalformedURLException Exception : check script url.");
                      Toast.makeText(UploadToServer.this, "MalformedURLException",
                                                          Toast.LENGTH_SHORT).show();
                  
              );

              Log.e("Upload file to server", "error: " + ex.getMessage(), ex); 
           catch (Exception e) 

              dialog.dismiss(); 
              e.printStackTrace();

              runOnUiThread(new Runnable() 
                  public void run() 
                      messageText.setText("Got Exception : see logcat ");

if you have problem not solve till you can visit here for complete example

【讨论】:

以上是关于Android获取图库图片Uri路径的主要内容,如果未能解决你的问题,请参考以下文章

Android基础篇 获取图库中图片路径返回不同

Android:如何获取匹配缩略图 URI 的文件路径?

android选择图片,通过uri获取路径

获取存储在 sd 卡 + android 中的图像的缩略图 Uri/路径

从URI获取真实路径,Android KitKat新的存储访问框架[重复]

以编程方式从 Android 的内置图库应用程序中获取/选择图像