转载: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>

为什么会不一样呢?

Android 4.4(含)开始,通过方式访问图库后,返回的Uri如下(访问“最近”):

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);
}
 拍照通用方法,对返回数据做处理: 
/**
* <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前后版本读取图库图片和拍照完美解决方案的更多相关文章

  1. 【转】Android 4.4前后版本读取图库图片和拍照完美解决方案

    http://blog.csdn.net/zbjdsbj/article/details/42387551 4.3或以下,选了图片之后,根据Uri来做处理,很多帖子都有了,我就不详细说了.主要是4.4 ...

  2. 【原创】Android 4.4前后版本读取图库图片方式的变化

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

  3. Mantis的附件图片实现预览/弹出层动画效果预览图片(LightBox2)的完美解决方案[Z]

    方法1: 在Mantis的配置文件中,加入此句,将这个值设的很大,就可以直接看到图片 1 $g_preview_attachments_inline_max_size=1000000; 效果如图 这个 ...

  4. Android 判断软键盘弹出并隐藏的简单完美解决方案

    最近项目中有一个编辑框,下面是个ListView.在触发编辑框弹出软键盘后,ListView还能滑动,并且ListView的item还能响应单击.这样的体验效果很不好.于是便想在滑动或单击item时判 ...

  5. 【Android】12.4 利用Intent读取图库中的图片

    分类:C#.Android.VS2015: 创建日期:2016-02-23 一.简介 该示例演示如何从图库(Gallery)中读取图像并用ImageView将它显示出来. 二.示例-ch1203Rea ...

  6. Android 简单图片浏览器 读取sdcard图片+形成缩略图+Gallery

    1.读取SD卡上面的图片信息 //想要的返回值所在的列 String[] projection = { MediaStore.Images.Thumbnails._ID}; //图片信息存储在 and ...

  7. Android取得图库图片的具体地址

    protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResu ...

  8. 搭建Android+QT+OpenCV环境,实现“单色图片着色”效果

               OpenCV是我们大家非常熟悉的图像处理开源类库:在其新版本将原本在Contrib分库中的DNN模块融合到了主库中,并且更新了相应文档.这样我们就能够非常方便地利用OpenCV实 ...

  9. Android外部SD卡的读取

    package com.kevin.writeorreadfile1_1; import android.app.Activity; import android.bluetooth.le.ScanF ...

随机推荐

  1. Jmail组件发送邮件说明ASP.NET

    ASP.Net环境下使用Jmail组件发送邮件2008-01-25 18:59实现过程: 不同于在Asp中使用Jmail,直接使用 Server.CreateObject("Jmail.Me ...

  2. (转)web.config详解之在文件中配置网站默认页面

    在<configuration></configuration>中添加下面的配置 <system.webServer>        <defaultDocu ...

  3. Tomcat 默认应用

    在部署应用时需要更改默认的端口号及应用,以免让别人知道使用的服务器类型而进行攻击.tomca的部署有多种方式,这里简单谈一下.目前想到有三种方式:一.添加 Context在Tomcat的配置文件中,一 ...

  4. 操作html标签之找到标签

    引入 丰富多彩的html标签构成了网页.例如p,div,li,ul,a......…….它们都有自己默认的样式,且各不一样,例如h1标签就比p标签的margin要大一些.我们学习css的目的是为了改变 ...

  5. nginx添加第三方模块

    原已经安装好的nginx,现在需要添加一个未被编译安装的模块: nginx -V 可以查看原来编译时都带了哪些参数,看看nginx是哪个版本,去下载一个nginx的源码,解压 原来的参数:--pref ...

  6. phpwind 去除init.phpwind.net统计功能

    修改的文件如下:global.phplib/staticpage.class.phprequire/template.phpsimple/index.php

  7. C#编程实现朴素贝叶斯算法下的情感分析

    C#编程实现 这篇文章做了什么 朴素贝叶斯算法是机器学习中非常重要的分类算法,用途十分广泛,如垃圾邮件处理等.而情感分析(Sentiment Analysis)是自然语言处理(Natural Lang ...

  8. mysql主从数据库复制

    http://blog.csdn.net/lgh1117/article/details/8786274 http://blog.csdn.net/libraworm/article/details/ ...

  9. UESTC 75 The Queen's New Necklaces

    题意:一个项链的珠子的颜色有若干种.每种颜色的珠子个数为Ai.求有多少种不同的项链? 我们考虑,如果旋转i个珠子,那么会产生gcd(n,i)个循环节,每个循环节的大小我们假设为K,那么如果有一个颜色的 ...

  10. Qt之四方分割器QuadSplitter

    在Qt经常会用到分割器QSplitter,可以对多个控件进行水平或者垂直分割,但有一些特殊的需求无法满足,比如:四方分割...QuadSplitter是qt-apps里面的一个应用,挺不错的,拿来和大 ...