这几天做了一个APP,需要读取本地相册图片获取图片的路径然后再进行进一步的处理。这个需要先获取图片的URI,然后根据URI获取图片路径,根据图片路径获取图片。图片URI有两种格式,一种是file开头,一种是content开头。网上查了资料,基本都是按Android的系统去进行区分的,什么Android4.4前,Android4.4后。但是本人经过测试,发现按Android系统进行区分是无效的。
先说图片URI格式,我测试后发现有这两种:
file:///storage/emulated/0/DCIM/Camera/IMG_20170613_132837.jpg和
content://media/external/images/media/1028。要获取的图片路径是:
/storage/emulated/0/DCIM/Camera/IMG_20170613_132837.jpg
本人使用的测试机华为Android4.4.4,6.0,7.0,魅蓝 Android5.1,魅族MX4 Android4.4.2,图片的URI都是content开头。使用红米Android6.0.1,中兴Android6.0,图片URI都是file开头。
基于此,发现根据Android版本去判断图片URI类型是不靠谱的。
现在我的做法:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
switch (requestCode) {
case SELECT_PHOTO_CODE://从相册获取图片
try{
final Uri imageUri = data.getData();
Log.e("imageUri:",imageUri+"");
String selectPhoto = getRealPathFromUri(this,imageUri);
Log.e("selectPhoto:",selectPhoto);
setImageCompressBitmap(selectPhoto);
}catch (Exception e){
e.printStackTrace();
}
break;
default:
break;
}
}
}
/**
* 根据图片的Uri获取图片的绝对路径。@uri 图片的uri
* @return 如果Uri对应的图片存在,那么返回该图片的绝对路径,否则返回null
*/
public static String getRealPathFromUri(Context context, Uri uri) {
if(context == null || uri == null) {
return null;
}
if("file".equalsIgnoreCase(uri.getScheme())) {
return getRealPathFromUri_Byfile(context,uri);
} else if("content".equalsIgnoreCase(uri.getScheme())) {
return getRealPathFromUri_Api11To18(context,uri);
}
// int sdkVersion = Build.VERSION.SDK_INT;
// if (sdkVersion < 11) {
// // SDK < Api11
// return getRealPathFromUri_BelowApi11(context, uri);
// }
//// if (sdkVersion < 19) {
//// SDK > 11 && SDK < 19
//// return getRealPathFromUri_Api11To18(context, uri);
// return getRealPathFromUri_ByXiaomi(context, uri);
//// }
// // SDK > 19
return getRealPathFromUri_AboveApi19(context, uri);//没用到
}
//针对图片URI格式为Uri:: file:///storage/emulated/0/DCIM/Camera/IMG_20170613_132837.jpg
private static String getRealPathFromUri_Byfile(Context context,Uri uri){
String uri2Str = uri.toString();
String filePath = uri2Str.substring(uri2Str.indexOf(":") + 3);
return filePath;
}
/**
* 适配api19以上,根据uri获取图片的绝对路径
*/
@SuppressLint("NewApi")
private static String getRealPathFromUri_AboveApi19(Context context, Uri uri) {
String filePath = null;
String wholeID = null;
wholeID = DocumentsContract.getDocumentId(uri);
// 使用':'分割
String id = wholeID.split(":")[1];
String[] projection = { MediaStore.Images.Media.DATA };
String selection = MediaStore.Images.Media._ID + "=?";
String[] selectionArgs = { id };
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection,
selection, selectionArgs, null);
int columnIndex = cursor.getColumnIndex(projection[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
return filePath;
}
/**
* //适配api11-api18,根据uri获取图片的绝对路径。
* 针对图片URI格式为Uri:: content://media/external/images/media/1028
*/
private static String getRealPathFromUri_Api11To18(Context context, Uri uri) {
String filePath = null;
String[] projection = { MediaStore.Images.Media.DATA };
CursorLoader loader = new CursorLoader(context, uri, projection, null,
null, null);
Cursor cursor = loader.loadInBackground();
if (cursor != null) {
cursor.moveToFirst();
filePath = cursor.getString(cursor.getColumnIndex(projection[0]));
cursor.close();
}
return filePath;
}
/**
* 适配api11以下(不包括api11),根据uri获取图片的绝对路径
*/
private static String getRealPathFromUri_BelowApi11(Context context, Uri uri) {
String filePath = null;
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = context.getContentResolver().query(uri, projection,
null, null, null);
if (cursor != null) {
cursor.moveToFirst();
filePath = cursor.getString(cursor.getColumnIndex(projection[0]));
cursor.close();
}
return filePath;
}
经过测试,上面的测试机型全部获得图片路径。
相关博客:Android 4.4 kitkat以上及以下根据uri获取路径的方法
Android | Display Selected Image and Its Real Path