Android 4.4前后版本读取图库图片方式的变化

Android 4.4前后版本读取图库图片方式的变化

 
本文讲述Android 4.4(KitKat)前后访问图库以及访问后通过图片路径读取图片的变化
 

Android 4.4(KitKat)以前:

访问图库(方法一):
1      /**
2      * Access the gallery to pick up an image. 
3      */
4      private   void  startPickPhotoActivity() {
5         Intent intent =  new  Intent(Intent. ACTION_GET_CONTENT );
6         intent.setType( "image/*" ); // Or ‘image/ jpeg ‘
7         startActivityForResult(intent,  RESULT_PICK_PHOTO_NORMAL );
8     }

访问图库(方法二):

1      /**
2      * Access the gallery to pick up an image. 
3      */
4      private   void  startPickPhotoActivity() {
5         Intent intent =  new  Intent(Intent. ACTION_GET_CONTENT );
6         intent.setType( "image/*" ); // Or ‘image/ jpeg ‘
7         Intent wrapperIntent = Intent. createChooser (intent,  null );
8         startActivityForResult(wrapperIntent,  RESULT_PICK_PHOTO_NORMAL );
9      }

 

获取文件路径&读取图片:
 1     @Override
 2     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 3         if (requestCode == RESULT_PICK_PHOTO_NORMAL) {
 4             if (resultCode == RESULT_OK && data != null) {
 5                 mFileName = DemoUtils.getDataColumn(getApplicationContext(),
 6                         data.getData(), null, null);
 7                 mColorBitmap = DemoUtils.getBitmap(mFileName);
 8 
 9                 mImage.setImageBitmap(mColorBitmap);
10             }
11         }
12     }
13 
14     public static final Bitmap getBitmap(String fileName) {
15         Bitmap bitmap = null;
16         try {
17             Options options = new Options();
18             options.inJustDecodeBounds = true;
19             BitmapFactory.decodeFile(fileName, options);
20             options.inSampleSize = Math.max(1, (int) Math.ceil(Math.max(
21                     (double) options.outWidth / 1024f,
22                     (double) options.outHeight / 1024f)));
23             options.inJustDecodeBounds = false;
24             bitmap = BitmapFactory.decodeFile(fileName, options);
25         } catch (OutOfMemoryError error) {
26             error.printStackTrace();
27         }
28 
29         return bitmap;
30     }
31 
32     /**
33      * Get the value of the data column for this Uri . This is useful for
34      * MediaStore Uris , and other file - based ContentProviders.
35      * 
36      * @param context
37      *            The context.
38      * @param uri
39      *            The Uri to query.
40      * @param selection
41      *            (Optional) Filter used in the query.
42      * @param selectionArgs
43      *            (Optional) Selection arguments used in the query.
44      * @return The value of the _data column, which is typically a file path.
45      */
46     public static String getDataColumn(Context context, Uri uri,
47             String selection, String[] selectionArgs) {
48         Cursor cursor = null;
49         final String column = MediaColumns.DATA;
50         final String[] projection = { column };
51         try {
52             cursor = context.getContentResolver().query(uri, projection,
53                     selection, selectionArgs, null);
54             if (cursor != null && cursor.moveToFirst()) {
55                 final int index = cursor.getColumnIndexOrThrow(column);
56                 return cursor.getString(index);
57             }
58         } finally {
59             if (cursor != null)
60                 cursor.close();
61         }
62         return null;
63     }

 

Android 4.4(KitKat)及以后:

访问图库(方法一):同上方法一
访问图库(方法二):同上方法二
访问图库(方法三):
1      /**
2      * Access the gallery to pick up an image. 
3      */
4      @TargetApi (Build.VERSION_CODES. KITKAT )
5      private   void  startPickPhotoActivity() {
6         Intent intent =  new  Intent(Intent. ACTION_OPEN_DOCUMENT );
7         intent.setType( "image/*" ); // Or ‘image/ jpeg ‘
8         startActivityForResult(intent,  RESULT_PICK_PHOTO_NORMAL );
9     }

 

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

 

为什么会不一样呢?

Android 4.4(含)开始,通过方式访问图库后,返回的Uri如下(访问“最近”):
1 Uri is:         content://com.android.providers.media.documents/document/image%3A18838
2 Uri.getPath is :/document/image:18838
3 对应的图片真实路径:/storage/emulated/0/Pictures/Screenshots/Screenshot_2014-09-22-21-40-53.png

不但如此,对于不同类型图库,返回的Uri形式并不相同(访问普通相册):

1 Uri is:         content://media/external/images/media/18822
2 Uri.getPath is :/external/images/media/18822
3 对应的图片真实路径:/storage/emulated/0/Download/20130224235013.jpg

而4.4之前返回的Uri只存在一种形式,如下:

1 Uri is:         content://media/external/images/media/14046
2 Uri.getPath is :/external/images/media/14046
3 对应的图片真实路径:/storage/emulated/0/DCIM/Camera/20130224235013.jpg

 

因此,在Android 4.4或更高版本设备上,通过简单的getDataColumn(Context, Uri, null, null)进行图片数据库已经不能满足所有需求,因此在获取图片真实路径的时候需要根据不同类型区分对待。
 
其实,有一种更为Simple&Lazy的方式,就是通过数据库查询时指定图片id,更为精确的查询图片。
1 // TODO 从Uri中读取图片id,如:/document/image/18838,   /external/images/media/14046
2 // String id = ...
3 // ......
4  
5 String selection = MediaColumns._ID + " = ?";
6 String[] selectionArgs = new String{ id };
7  
8 Uri queryUri = "content://media/external/images/media";
9 String fileName = getDataColumns(context, queryUri, selection, selectionArgs );

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。