您的位置:首页 > 产品设计 > UI/UE

关于从图库选择图片的问题,Android4.4前后的改动,顺便吐槽小米MIUI

2016-04-09 11:26 573 查看
项目中有需求是要从图库中选择图片并显示的。这个需求,网上一搜一大把,我也不想炒剩饭了。只是将自己碰到的一些问题,讲出来,供大家参考,规避类似问题。

最开始,我调用系统图库,没考虑过版本问题,直到找了台小米机测试,才发现问题所在。按理说,我应该感谢小米的,别急,后面就知道我为啥吐槽它了。

我调用系统图库的是ACTION_PICK,回调方法onactivityresult里代码如下:

if (requestCode==Conts.LOAD_PICTURE) {

if (resultCode==getActivity().RESULT_OK&&data!=null) {

Uri selectedImage = data.getData();

String[] filePathColumn = { MediaStore.Images.Media.DATA };

Cursor cursor = getContext().getContentResolver().query(selectedImage,

filePathColumn, null, null, null);

cursor.moveToFirst();

int columnIndex = cursor.getColumnIndex(filePathColumn[0]);

String picturePath = cursor.getString(columnIndex);

cursor.close();

}

选择了图片之后,小米机会崩掉(别的机子,啥版本都没问题),或者返回上一层界面,或者重启app。看异常信息。指示cursor.moveToFirst(),空指针异常。也就是说,cursor为空。是uri的问题,4.4之前,返回的是包含图片绝对路劲的,4.4之后,返回的不再是绝对路劲了,而是一个图片的编码。但是,Android肯定不会这么坑,对吧,他绝对会兼容之前的版本。如果用的是ACTION_PICK,还是可以用这个方法的,但是他只能选择系统图库里的图片,例如“最近”,“图片”,“文件夹”什么的,就看不到了。不过至少给了个方法,是吧。华为,三星,魅族,oppo,都试过了,没有问题。而小米呢,又开始发扬其作屎风格了,不论版本高低,这样都不行,都会出现我上面提到的问题。得到的只是一个图片编码。你需要去转换为绝对路径,才能方便使用。得到绝对路径的方法,有大神封装好了,封装成了一个pictureHelper工具类,最后我会把这个类的代码贴上。

总结一下,就是,除了小米,你用ACTION_PICK,都能得到一个图片的绝对路径。如果是小米,用ACTION_PICK,就需要去转化了。但是,小米用ACTION_GET_CONTENT或者ACTION_OPEN_DOCUMENT,低版本,也能得到绝对路径。反正我是醉了。最后我统一的处理方法就是,用ACTION_GET_CONTENT,然后分版本处理,低版本还是旧的方法,高版本,用pictureHelper工具类处理得到绝对路径。

贴代码,调用图库Intent intent= new Intent(Intent.ACTION_GET_CONTENT);// ACTION_OPEN_DOCUMENT

// intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); //4.4推荐用此方式,4.4以下的API需要再兼容

intent.addCategory(Intent.CATEGORY_OPENABLE);

intent.setType("image/*");

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {

startActivityForResult(intent, Conts.LOAD_PICTURE_KITKAK);//4.4版本

} else {

startActivityForResult(intent, Conts.LOAD_PICTURE);//4.4以下版本,先不处理

}

在onactivityresult里的处理://上面的是低版本的,下面一种是高版本

if (requestCode==Conts.LOAD_PICTURE) {

if (resultCode==getActivity().RESULT_OK&&data!=null) {

Uri selectedImage = data.getData();

String[] filePathColumn = { MediaStore.Images.Media.DATA };

Cursor cursor = getContext().getContentResolver().query(selectedImage,

filePathColumn, null, null, null);

cursor.moveToFirst();

int columnIndex = cursor.getColumnIndex(filePathColumn[0]);

String picturePath = cursor.getString(columnIndex);

cursor.close();

}

}

//4.4以上版本

if (requestCode==Conts.LOAD_PICTURE_KITKAK) {

if (resultCode==getActivity().RESULT_OK&&data!=null) {

Uri selectedImage = data.getData();

String picturePath = PictureHelper.getPath(getContext(), selectedImage);

}

}

还有个我遇到的问题也顺带提一句,如果,你在onactivityresult里有很多操作,比较耗时的话,也会崩掉,响应事件过长导致的。我的处理方法是,这些处理用工作线程完成,处理完毕,handler发消息给主线程去完成UI操作。这个大家估计问题不大,只是有时会忽视。

好了,进入正题,吐槽开始。小米,从他整出MIUI,就没消停过,擅自更改UI样式等等,就不提了,Android的很多设计原则,他丫就是不准守,他的原则只有一个,就是舔的用户开心,完全不管开发者的感受。反正用户骂的不会是系统,只会骂开发者,这个app做的真烂。之前还有个drawable里放图片资源也遇到过,别人的这么放的都好使,他的就不行,闪退,还是去查了好久资料,按照他的规则来,才解决图片资源加载的问题。总之,Android碎片化如此严峻的今天,我们又要多一种适配出来,那就是该屎的小米。你在开发中,必须考虑你的app在小米机上,会不会正常运行。我要是能做主,我的app就尼玛不兼容小米。爱咋咋地。可惜......

最后把那个PictureHelper工具类附上。

public class PictureHelper {

// get the absolute path from the uri

@SuppressLint("NewApi")

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];

}

// TODO handle non-primary volumes

}

// 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;

}

public static boolean isExternalStorageDocument(Uri uri) {

return "com.android.externalstorage.documents".equals(uri

.getAuthority());

}

public static boolean isDownloadsDocument(Uri uri) {

return "com.android.providers.downloads.documents".equals(uri

.getAuthority());

}

public static boolean isMediaDocument(Uri uri) {

return "com.android.providers.media.documents".equals(uri

.getAuthority());

}

private static boolean isGooglePhotosUri(Uri uri) {

return "com.google.android.apps.photos.content".equals(uri

.getAuthority());

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: