zoukankan      html  css  js  c++  java
  • 系统图片uri的问题

             调用系统图库会出现两种uri的问题,一个是在文件管理器中的图库中,获取到的地址为:content://media/external/images/media/972  这种格式

             另外一种的是系统文件管理器的图片选选项中,获取到的路径格式为:content://com.android.providers.media.documents/document/image%3A972

             听别人解释,这两种路径,第一种是下面这种的映射,也就是根据第一种可以拿到第二种,但个人还是不太明白。看到的高人请指点啊。

             这两种uri的主要问题出在,如果设置图片使用  setImageUri(uri) 时,二者都没问题。

             但是如果要把该uri转换成图片的路径,下面的长的路径转化出来为null。上面的ok。

              

             我的转化方法如下:

         Uri uri = data.getData();
         ContentResolver resolver = getContentResolver();

        Cursor cursor = resolver.query(uri,
        new String[]{MediaStore.Images.Media.DATA}, null, null, null);
    cursor.moveToFirst();
    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));

            

      以下为引用别人博客

    出处:http://blog.csdn.net/tempersitu/article/details/20557383

          

    1. Intent intent=new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);  

    的 方式来做,是调用系统图库来做,但是发现如果有图片是同步到google相册的话,图库里面能看到一个auto backup的目录,点进去选图片的话是无法获取到图片的路径的.因为那些图片根本就不存在于手机上.然后看到无论是百度贴吧,Instagram,或者 还有些会选取图片做修改的app,都是用一个很漂亮的图片选择器(4.4以上,4.3的还是用系统旧的图库).




    而这个图片选择器可以屏蔽掉那个auto backup的目录.所以就开始打算用这个图片选择器来选图片了.
    这个方法就是

    1. Intent intent=new Intent(Intent.ACTION_GET_CONTENT);//ACTION_OPEN_DOCUMENT  
    2. intent.addCategory(Intent.CATEGORY_OPENABLE);  
    3. intent.setType("image/jpeg");  
    4. if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.KITKAT){                  
    5.         startActivityForResult(intent, SELECT_PIC_KITKAT);    
    6. }else{                
    7.         startActivityForResult(intent, SELECT_PIC);   
    8. }   


    为什么要分开不同版本呢?其实在4.3或以下可以直接用ACTION_GET_CONTENT的,在4.4或以上,官方建议用ACTION_OPEN_DOCUMENT,但其实都不算太大区别,区别是他们返回的Uri,那个才叫大区别.这就是困扰了我一整天的问题所在了.

    4.3或以下,选了图片之后,根据Uri来做处理,很多帖子都有了,我就不详细说了.主要是4.4,如果使用上面pick的原生方法来选图,返回的uri 还是正常的,但如果用ACTION_GET_CONTENT的方法,返回的uri跟4.3是完全不一样的,4.3返回的是带文件路径的,而4.4返回的却 是content://com.android.providers.media.documents/document/image:3951这样的, 没有路径,只有图片编号的uri.这就导致接下来无法根据图片路径来裁剪的步骤了.

    还好找了很多方法,包括加权限啊什么的,中间还试过用一些方法,自己的app没崩溃,倒是让系统图库崩溃了,引发了java.lang.SecurityException.

     

    1. Caused by: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{437b5d88 9494:com.google.android.gallery3d/u0a20} (pid=9494, uid=10020) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS  


    看来4.4的系统还是有些bug.重点来了,4.4得到的uri,需要以下方法来获取文件的路径


     

    1. public static String getPath(final Context context, final Uri uri) {  
    2.   
    3.     final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;  
    4.   
    5.     // DocumentProvider  
    6.     if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {  
    7.         // ExternalStorageProvider  
    8.         if (isExternalStorageDocument(uri)) {  
    9.             final String docId = DocumentsContract.getDocumentId(uri);  
    10.             final String[] split = docId.split(":");  
    11.             final String type = split[0];  
    12.   
    13.             if ("primary".equalsIgnoreCase(type)) {  
    14.                 return Environment.getExternalStorageDirectory() + "/" + split[1];  
    15.             }  
    16.   
    17.             // TODO handle non-primary volumes  
    18.         }  
    19.         // DownloadsProvider  
    20.         else if (isDownloadsDocument(uri)) {  
    21.   
    22.             final String id = DocumentsContract.getDocumentId(uri);  
    23.             final Uri contentUri = ContentUris.withAppendedId(  
    24.                     Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));  
    25.   
    26.             return getDataColumn(context, contentUri, null, null);  
    27.         }  
    28.         // MediaProvider  
    29.         else if (isMediaDocument(uri)) {  
    30.             final String docId = DocumentsContract.getDocumentId(uri);  
    31.             final String[] split = docId.split(":");  
    32.             final String type = split[0];  
    33.   
    34.             Uri contentUri = null;  
    35.             if ("image".equals(type)) {  
    36.                 contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;  
    37.             } else if ("video".equals(type)) {  
    38.                 contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;  
    39.             } else if ("audio".equals(type)) {  
    40.                 contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;  
    41.             }  
    42.   
    43.             final String selection = "_id=?";  
    44.             final String[] selectionArgs = new String[] {  
    45.                     split[1]  
    46.             };  
    47.   
    48.             return getDataColumn(context, contentUri, selection, selectionArgs);  
    49.         }  
    50.     }  
    51.     // MediaStore (and general)  
    52.     else if ("content".equalsIgnoreCase(uri.getScheme())) {  
    53.   
    54.         // Return the remote address  
    55.         if (isGooglePhotosUri(uri))  
    56.             return uri.getLastPathSegment();  
    57.   
    58.         return getDataColumn(context, uri, null, null);  
    59.     }  
    60.     // File  
    61.     else if ("file".equalsIgnoreCase(uri.getScheme())) {  
    62.         return uri.getPath();  
    63.     }  
    64.   
    65.     return null;  
    66. }  
    67.   
    68. /** 
    69.  * Get the value of the data column for this Uri. This is useful for 
    70.  * MediaStore Uris, and other file-based ContentProviders. 
    71.  * 
    72.  * @param context The context. 
    73.  * @param uri The Uri to query. 
    74.  * @param selection (Optional) Filter used in the query. 
    75.  * @param selectionArgs (Optional) Selection arguments used in the query. 
    76.  * @return The value of the _data column, which is typically a file path. 
    77.  */  
    78. public static String getDataColumn(Context context, Uri uri, String selection,  
    79.         String[] selectionArgs) {  
    80.   
    81.     Cursor cursor = null;  
    82.     final String column = "_data";  
    83.     final String[] projection = {  
    84.             column  
    85.     };  
    86.   
    87.     try {  
    88.         cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,  
    89.                 null);  
    90.         if (cursor != null && cursor.moveToFirst()) {  
    91.             final int index = cursor.getColumnIndexOrThrow(column);  
    92.             return cursor.getString(index);  
    93.         }  
    94.     } finally {  
    95.         if (cursor != null)  
    96.             cursor.close();  
    97.     }  
    98.     return null;  
    99. }  
    100.   
    101.   
    102. /** 
    103.  * @param uri The Uri to check. 
    104.  * @return Whether the Uri authority is ExternalStorageProvider. 
    105.  */  
    106. public static boolean isExternalStorageDocument(Uri uri) {  
    107.     return "com.android.externalstorage.documents".equals(uri.getAuthority());  
    108. }  
    109.   
    110. /** 
    111.  * @param uri The Uri to check. 
    112.  * @return Whether the Uri authority is DownloadsProvider. 
    113.  */  
    114. public static boolean isDownloadsDocument(Uri uri) {  
    115.     return "com.android.providers.downloads.documents".equals(uri.getAuthority());  
    116. }  
    117.   
    118. /** 
    119.  * @param uri The Uri to check. 
    120.  * @return Whether the Uri authority is MediaProvider. 
    121.  */  
    122. public static boolean isMediaDocument(Uri uri) {  
    123.     return "com.android.providers.media.documents".equals(uri.getAuthority());  
    124. }  
    125.   
    126. /** 
    127.  * @param uri The Uri to check. 
    128.  * @return Whether the Uri authority is Google Photos. 
    129.  */  
    130. public static boolean isGooglePhotosUri(Uri uri) {  
    131.     return "com.google.android.apps.photos.content".equals(uri.getAuthority());  
    132. }  


    这样,就可以在4.4上用漂亮的图片选择器,选到我们想要的文件,又不会出问题了.


    昨天发现了个bug,如果在4.4上面不用"图片"来选,用"图库"来选,就会无法读取到图片路径,所以只需要加个判断,如果是用旧方式来选,就用旧方式来读,就是如果
    DocumentsContract.isDocumentUri(context, uri) 返回false的话,就用旧的方式


      1. public static String selectImage(Context context,Intent data){  
      2.         Uri selectedImage = data.getData();  
      3. //      Log.e(TAG, selectedImage.toString());  
      4.         if(selectedImage!=null){              
      5.             String uriStr=selectedImage.toString();  
      6.             String path=uriStr.substring(10,uriStr.length());  
      7.             if(path.startsWith("com.sec.android.gallery3d")){  
      8.                 Log.e(TAG, "It's auto backup pic path:"+selectedImage.toString());  
      9.                 return null;  
      10.             }  
      11.         }         
      12.         String[] filePathColumn = { MediaStore.Images.Media.DATA };  
      13.         Cursor cursor = context.getContentResolver().query(selectedImage,filePathColumn, null, null, null);  
      14.         cursor.moveToFirst();  
      15.         int columnIndex = cursor.getColumnIndex(filePathColumn[0]);  
      16.         String picturePath = cursor.getString(columnIndex);  
      17.         cursor.close();  
      18.         return picturePath;       
      19.     } 
  • 相关阅读:
    hdu5728 PowMod
    CF1156E Special Segments of Permutation
    CF1182E Product Oriented Recurrence
    CF1082E Increasing Frequency
    CF623B Array GCD
    CF1168B Good Triple
    CF1175E Minimal Segment Cover
    php 正则
    windows 下安装composer
    windows apache "The requested operation has failed" 启动失败
  • 原文地址:https://www.cnblogs.com/epmouse/p/5344792.html
Copyright © 2011-2022 走看看