【转】Android 4.4前后版本读取图库图片和拍照完美解决方案
http://blog.csdn.net/zbjdsbj/article/details/42387551
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.这就导致接下来无法根据图片路径来裁剪的步骤了.
来自overflow大牛的方法,4.4得到的uri,需要以下方法来获取文件的路径:
- /**
- * <br>功能简述:4.4及以上获取图片的方法
- * <br>功能详细描述:
- * <br>注意:
- * @param context
- * @param uri
- * @return
- */
- @TargetApi(Build.VERSION_CODES.KITKAT)
- 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];
- }
- }
- // 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;
- }
- 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());
- }</span></span>
为什么会不一样呢?
- 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</span>
不但如此,对于不同类型图库,返回的Uri形式并不相同(访问普通相册):
- Uri is:content://media/external/images/media/18822
- 2 Uri.getPath is :/external/images/media/18822
- 3 对应的图片真实路径:/storage/emulated/0/Download/20130224235013.jpg</span>
而4.4之前返回的Uri只存在一种形式,如下:
- 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)进行图片数据库已经不能满足所有需求,因此在获取图片真实路径的时候需要根据不同类型区分对待。
版本判断:
- //版本比较:是否是4.4及以上版本
- final boolean mIsKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
从相册选择照片方法比较:
- /**
- * <br>功能简述:4.4及以上从相册选择照片
- * <br>功能详细描述:
- * <br>注意:
- */
- @TargetApi(Build.VERSION_CODES.KITKAT)
- private void SelectImageUriAfterKikat() {
- Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
- intent.addCategory(Intent.CATEGORY_OPENABLE);
- intent.setType("image/*");
- startActivityForResult(intent, SELECET_A_PICTURE_AFTER_KIKAT);
- }
- /**
- * <br>功能简述:4.4以下从相册选照片并剪切
- * <br>功能详细描述:
- * <br>注意:
- */
- private void cropImageUri() {
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
- intent.setType("image/*");
- intent.putExtra("crop", "true");
- intent.putExtra("aspectX", 1);
- intent.putExtra("aspectY", 1);
- intent.putExtra("outputX", 640);
- intent.putExtra("outputY", 640);
- intent.putExtra("scale", true);
- intent.putExtra("return-data", false);
- intent.putExtra(MediaStore.EXTRA_OUTPUT,
- Uri.fromFile(new File(IMGPATH, TMP_IMAGE_FILE_NAME)));
- intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
- intent.putExtra("noFaceDetection", true); // no face detection
- startActivityForResult(intent, SELECT_A_PICTURE);
- }
4.4及以上选取照片后需要调用剪切方法:
- /**
- * <br>功能简述: 4.4及以上选取照片后剪切方法
- * <br>功能详细描述:
- * <br>注意:
- * @param uri
- */
- private void cropImageUriAfterKikat(Uri uri) {
- Intent intent = new Intent("com.android.camera.action.CROP");
- intent.setDataAndType(uri, "image/*");
- intent.putExtra("crop", "true");
- intent.putExtra("aspectX", 1);
- intent.putExtra("aspectY", 1);
- intent.putExtra("outputX", 640);
- intent.putExtra("outputY", 640);
- intent.putExtra("scale", true);
- intent.putExtra("return-data", true); //返回数据bitmap
- intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
- intent.putExtra("noFaceDetection", true); // no face detection
- startActivityForResult(intent, SET_ALBUM_PICTURE_KITKAT);
- }
拍照通用方法,对返回数据做处理:
- /**
- * <br>功能简述:对拍照的图片剪切
- * <br>功能详细描述:
- * <br>注意:
- * @param uri
- */
- private void cameraCropImageUri(Uri uri) {
- Intent intent = new Intent("com.android.camera.action.CROP");
- intent.setDataAndType(uri, "image/jpeg");
- intent.putExtra("crop", "true");
- intent.putExtra("aspectX", 1);
- intent.putExtra("aspectY", 1);
- intent.putExtra("outputX", 640);
- intent.putExtra("outputY", 640);
- intent.putExtra("scale", true);
- if (mIsKitKat) {
- intent.putExtra("return-data", true);
- } else {
- intent.putExtra("return-data", false);
- intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
- }
- intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
- intent.putExtra("noFaceDetection", true);
- startActivityForResult(intent, SET_PICTURE);
- }
显示等处理如下:
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- if (requestCode == SELECT_A_PICTURE) {
- if (resultCode == RESULT_OK && null != data) {
- Log.i("zou", "4.4以下的");
- Bitmap bitmap = decodeUriAsBitmap(Uri.fromFile(new File(IMGPATH,
- TMP_IMAGE_FILE_NAME)));
- mAcountHeadIcon.setImageBitmap(bitmap);
- }
- } else if (requestCode == SELECET_A_PICTURE_AFTER_KIKAT) {
- if (resultCode == RESULT_OK && null != data) {
- Log.i("zou", "4.4以上上的");
- mAlbumPicturePath = getPath(MainActivity.this, data.getData());
- cropImageUriAfterKikat(Uri.fromFile(new File(mAlbumPicturePath)));
- }
- } else if (requestCode == SET_ALBUM_PICTURE_KITKAT) {
- Log.i("zou", "4.4以上上的 RESULT_OK");
- Bitmap bitmap = data.getParcelableExtra("data");
- mAcountHeadIcon.setImageBitmap(bitmap);
- } else if (requestCode == TAKE_A_PICTURE) {
- Log.i("zou", "resultCode:" + resultCode);
- cameraCropImageUri(Uri.fromFile(new File(IMGPATH, IMAGE_FILE_NAME)));
- } else if (requestCode == SET_PICTURE) {
- Log.i("zou", "SET_PICTURE-resultCode:" + resultCode);
- Bitmap bitmap = null;
- if (mIsKitKat) {
- if (null != data) {
- bitmap = data.getParcelableExtra("data");
- }
- } else {
- bitmap = decodeUriAsBitmap(Uri.fromFile(new File(IMGPATH, IMAGE_FILE_NAME)));
- }
- mAcountHeadIcon.setImageBitmap(bitmap);
- }
- }
GIthub工程地址:https://github.com/ZBJDSBJ/CameraDemo
【转】Android 4.4前后版本读取图库图片和拍照完美解决方案的更多相关文章
- Android 4.4前后版本读取图库图片和拍照完美解决方案
转载:http://blog.csdn.net/zbjdsbj/article/details/42387551 4.3或以下,选了图片之后,根据Uri来做处理,很多帖子都有了,我就不详细说了. 主要 ...
- 【原创】Android 4.4前后版本读取图库图片方式的变化
Android 4.4前后版本读取图库图片方式的变化 本文讲述Android 4.4(KitKat)前后访问图库以及访问后通过图片路径读取图片的变化 Android 4.4(KitKat)以前 ...
- Android 判断软键盘弹出并隐藏的简单完美解决方案
最近项目中有一个编辑框,下面是个ListView.在触发编辑框弹出软键盘后,ListView还能滑动,并且ListView的item还能响应单击.这样的体验效果很不好.于是便想在滑动或单击item时判 ...
- 【Android】12.4 利用Intent读取图库中的图片
分类:C#.Android.VS2015: 创建日期:2016-02-23 一.简介 该示例演示如何从图库(Gallery)中读取图像并用ImageView将它显示出来. 二.示例-ch1203Rea ...
- 快速解决设置Android 23.0以上版本对SD卡的读写权限无效的问题
快速解决设置Android 23.0以上版本对SD卡的读写权限无效的问题 转 https://www.jb51.net/article/144939.htm 今天小编就为大家分享一篇快速解决设置And ...
- Android外部SD卡的读取
package com.kevin.writeorreadfile1_1; import android.app.Activity; import android.bluetooth.le.ScanF ...
- Android应用在不同版本间兼容性处理
在Android系统中向下兼容性比较差,但是一个应用APP经过处理还是可以在各个版本间运行的.向下兼容性不好,不同版本的系统其API版本也不同,自然有些接口也不同,新的平台不能使用旧的API,旧的平台 ...
- Android SDK与API版本的对应关系
看教程.开发Android程序等很多地方,需要设置Android SDK的版本,而其要我们写的却是API版本的数字, 为了方便查看 Android SDK与API版本的对应关系 我在SDK Manag ...
- 【Android】Android Studio3.1 Mac版本设置项目桌面icon
近来项目处于测试阶段,工作少了许多,就装了个最新的Android Studio,想写一下安卓.新建好项目,想设置个桌面的icon.我先准备好自己的icon图片,然后复制粘贴到res/mipmap-hd ...
随机推荐
- OK335xS mac address hacking
/*********************************************************************** * OK335xS mac address hacki ...
- HDU 2444 The Accomodation of Students (偶图判定,匈牙利算法)
题意: 有一堆的学生关系,要将他们先分成两个组,同组的人都不互不认识,如果不能分2组,输出No.若能,则继续.在两组中挑两个认识的人(每组各1人)到一个双人房.输出需要多少个双人房? 思路: 先判定是 ...
- 使用D3D渲染YUV视频数据
源代码下载 在PC机上,对于YUV格式的视频如YV12,YUY2等的显示方法,一般是采用DIRECTDRAW,使用显卡的OVERLAY表面显示.OVERLAY技术主要是为了解决在PC上播放VCD而在显 ...
- 【jQuery】jQuery筛选器规则
转载自:http://blog.csdn.net/lijinwei112/article/details/6938134 筛选器中加入变量 var ac = "select_" + ...
- solr4.5配置中文分词器mmseg4j
solr4.x虽然提供了分词器,但不太适合对中文的分词,给大家推荐一个中文分词器mmseg4j mmseg4j的下载地址:https://code.google.com/p/mmseg4j/ 通过以下 ...
- JTA事务管理--配置剖析
概述 [IT168 专稿]Spring 通过AOP技术可以让我们在脱离EJB的情况下享受声明式事务的丰盛大餐,脱离Java EE应用服务器使用声明式事务的道路已经畅通无阻.但是很大部分人都还认为 ...
- 使用七牛云存储----大家自己的图床[python]
##写博客什么的总得贴图吧,图床选来选去还是七牛吧.嗯,就是你了 [OSchaina 源码] 结合FastStone Capture 简直爽歪歪. FastStone Capture 自动保存图片到文 ...
- ASP.NET常用技巧方法代码断
1. 打开新的窗口并传送参数:传送参数:response.write("<script>window.open('*.aspx?id="+this.DropDownLi ...
- 我是怎么发现并解决项目页面渲染效率问题的(IE调试工具探查器的使用)
#我是怎么发现并解决项目页面渲染效率问题的(IE调试工具探查器的使用) ##背景 之前的项目中,有很多的登记页面,一般都有100-200甚至更加多的字段,而且还涉及到字典.日期及其他效果的显示,载入时 ...
- How to interact with the Chef Server using the Chef Server API using Shell script
!/usr/bin/env bash _chef_dir () { # Helper function: # Recursive function that searches for chef c ...