首页 > 代码库 > 【原创】Android 4.4前后版本读取图库图片方式的变化
【原创】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 for34 * MediaStore Uris , and other file - based ContentProviders.35 * 36 * @param context37 * The context.38 * @param uri39 * The Uri to query.40 * @param selection41 * (Optional) Filter used in the query.42 * @param selectionArgs43 * (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 uri106 * 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(uri111 .getAuthority());112 }113 114 /**115 * @param uri116 * 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(uri121 .getAuthority());122 }123 124 /**125 * @param uri126 * 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(uri131 .getAuthority());132 }133 134 /**135 * @param uri136 * 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(uri141 .getAuthority());142 }
为什么会不一样呢?
Android 4.4(含)开始,通过方式访问图库后,返回的Uri如下(访问“最近”):
1 Uri is: content://com.android.providers.media.documents/document/image%3A188382 Uri.getPath is :/document/image:188383 对应的图片真实路径:/storage/emulated/0/Pictures/Screenshots/Screenshot_2014-09-22-21-40-53.png
不但如此,对于不同类型图库,返回的Uri形式并不相同(访问普通相册):
1 Uri is: content://media/external/images/media/188222 Uri.getPath is :/external/images/media/188223 对应的图片真实路径:/storage/emulated/0/Download/20130224235013.jpg
而4.4之前返回的Uri只存在一种形式,如下:
1 Uri is: content://media/external/images/media/140462 Uri.getPath is :/external/images/media/140463 对应的图片真实路径:/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/140462 // 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 );
【原创】Android 4.4前后版本读取图库图片方式的变化
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。