【原创】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)进行图片数据库已经不能满足所有需求,因此在获取图片真实路径的时候需要根据不同类型区分对待。
作者:Nodin
出处:http://www.cnblogs.com/monodin
个人博客网站:http://www.coderself.com
关于作者:爱摄影,爱旅行,爱自由,爱生活,更要爱自己。活在当下,也在为未来打拼!
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。