android打开系统图库终极适配
来源:互联网 发布:php 整数 编辑:程序博客网 时间:2024/05/21 22:55
原文地址:http://blog.csdn.net/nbalichaoq
android中调用系统图库本来是一个很基本的东西,几乎每个app都用的到(最基本的更换用户头像),网上的相关
容很多,本来找了几篇看了一下,拿几台测试机试了一下感觉就没什么问题了,但是适配问题慢慢就来了。
一.打开图库的基本方法。
通过查询资料,调用系统图库基本有3种方法。
1.使用Intent.ACTION_PICK
Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media. EXTERNAL_CONTENT_URI); //调用android的图库//i.setType("image/*");//不可设置type,否则noactivityfoundstartActivityForResult(Intent. createChooser(i,null) , 2) ;
这个intent在android6.0以下是可以用的,但是到了6.0就无效了,具体打印log忘记了,官方文档也只用了这
Intent来获取留联系人,所以pass掉。
2.使用Intent.ACTION_GET_CONTENT
Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT) ; //"android.intent.action.GET_CONTENT"innerIntent.setType( "image/*"); //查看类型 String IMAGE_UNSPECIFIED = "image/*";innerIntent.addCategory(Intent. CATEGORY_OPENABLE );startActivityForResult(Intent. createChooser(innerIntent, null) , 2) ;
并且有个bool型的extra EXTRA_ALLOW_MULTIPLE来支持多选功能(4.3及以上版本支持)。
官方文档上说,这个intent是用来“检索一个特定类型的文件”并且回返回检索到的文件的一个引用(文件的copy)
这个貌似是可以用的,而且也是大多数人选择。
3.使用Intent.ACTION_OPEN_DOCUMENT
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT) ;intent.addCategory(Intent. CATEGORY_OPENABLE);intent.setType("image/*") ;startActivityForResult(intent , 2) ;
这个action只支持4.4以上的版本。官方文档上说,这个intent是用来“打开一个特定类型的文件”,与检索相比
感觉跟适合我们的应用场景。同样可以使用EXTRA_ALLOW_MULTIPLE来支持多选。这个貌似更适合,只是需要判断sd
版本,4.4及以上使用ACTION_OPEN_DOCUMENT,4.3及以下使用ACTION_OPEN_DOCUMENT,这也是一些比较好的攻略里
使用方法。
二.选择图片后,图片文件的解析
当在系统图库中选择好图片后,可以在进入图库的Activity的onActivityResult()方法中通过返回的Uri进行解析
并且理论上Uri是content形式。而android的存储框架在4.4进行了一次改变。
(1)4.3及以下返回的uri是content://media/external/images/media/3951的形式,文件解析方式如下:
protected void onActivityResult( int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data) ; if(requestCode== 2&&Activity.RESULT_OK==resultCode&& null!=data){ Uri selectedImage = data.getData(); String picturePath = null; try { String[] filePathColumns={MediaStore.Images.Media.DATA} ; Cursor c = this.getContentResolver().query(selectedImage, filePathColumns, null,null, null) ; c.moveToFirst() ; int columnIndex = c.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//getColumnIndex(filePathColumns[0]); picturePath= c.getString(columnIndex) ; c.close() ; } catch (Exception e) { picturePath = selectedImage.getPath(); } Bundle bdl = new Bundle(); if(picturePath != null){ bdl.putString("image", picturePath); UIUtil. openActivity(this, PicCutActivity. class, bdl, 3); }
4.4及以上返回的uri是content://com.android.providers.media.documents/document/image:3952的形式,
析方式如下:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if(requestCode==2&&Activity.RESULT_OK==resultCode&&null!=data){Uri selectedImage = data.getData();String picturePath = selectedImage.getPath();try {final String docId = DocumentsContract.getDocumentId(selectedImage);final String[] split = docId.split(":");final String type = split[0];Uri contentUri = null;if ("primary".equalsIgnoreCase(type)) {picturePath = Environment.getExternalStorageDirectory() + "/" + split[1];} else {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]};picturePath = FileUtils.getDataColumn(this, contentUri, selection, selectionArgs);}} catch (Exception e) {picturePath = selectedImage.getPath();}}
三.结论,最终的适配方案
1.出现问题前
最开始,我使用的方法打开系统图库的方法是第三种方法中的适配方法。
(1)打开图库:
if(sdk版本<4.4)使用Intent.ACTION_GET_CONTENT打开图库else使用Intent.ACTION_OPEN_DOCUMENT打开图库
(2)解析uri获取文件路径:
if(sdk版本<4.4)使用第一种解析方式else使用第二种解析方法
貌似一切都逻辑都很合理,但最终都被碎片化的各个android手机厂商的定制系统给打破了。
2.问题出现
(1)第一个出现的问题是小米手机,测试的各种版本的小米手机都是4.4以上的系统,使
Intent.ACTION_OPEN_DOCUMENT,哪怕是通过setYpe("image/*")
设置了MIME type为图片,小米系统却还是给你打开了一个树形目录的文件管理器。虽然理论上我们应该去尽快适
android版本的更新,使用最新的api,但是现实中,我们只有使用Intent.ACTION_GET_CONTENT。
(2)
现在确定使用了Intent.ACTION_GET_CONTENT,而使用该Intent返回的Uri类型可以是content:// ;file:// ;
http://中的一种(Intent.ACTION_OPEN_DOCUMENT只有content://一种,虽然不用,但还是了解一下的好),虽然
论上打开图库返回的都应该是content://的类型,但测试中确实发现有有个别机型直接就返回了file://形式的文
路径,因此需要先判断是否直接返回了文件路径,是的文件路径的话就不用解析,否则进行解析。
(3)随着测试的机型的增多,理论上4.4以上的机型返回的content形式的Uri都是应该第二种解析方法适用的格式,
某些机型却会返回第一种解析方法适用的格式,并在解析过程中抛出异常。由于两种解析方式的原理我并没有仔细
研究,于是就在catch语句块中再进行了一次解析。
3.综上所述,我的打开图库的策略如下
(1)打开图库使用Intent.ACTION_GET_CONTENT
(2)选择图片文件解析:
Uri selectedImage = data.getData();//data是onActivityResult返回的intentString picturePath = selectedImage.getPath();if(!new File(picturePath).exists){//1.判断返回的uri是否是file:// 类型try{if(sdk < 4.4)第一种解析方式//2. 4.4以下版本使用第一种方式else 第二种解析方式//3. 4.4及以上使用第二种方式}catch(Exception e){try{if(sdk >= 4.4)第一种解析方式//4. 4.4及以上使用第二种方式抛出异常,则用第一种方式再解析一次}catch(..){..}}}
若使用第一种解析方式抛出异常(虽然我没有遇见过),则picturePath = selectedImage.getPath();。在使
picturePath时最好再判断一下文件是否存在。以上就是我自己总结的逻辑,虽然实现方式也许不是很好,但逻辑
算是比较周全了,欢迎指正。
- android打开系统图库终极适配
- android 打开系统图库的方法
- Android 打开系统图库实现方法
- 打开系统图库
- android 调用系统图库打开指定路径的图片
- Android启动系统相机,打开图库选择图片
- Android 刷新系统图库
- IOS 获取系统图库与打开拍照
- android的系统图库在
- ContentResolver访问android系统图库
- 打开图库
- Android中使用Intent打开本地图库
- Android从系统图库拿到文件--重命名--通知图库更新
- Android系统终极加速
- 主动通知Android系统图库进行更新
- android 从系统图库中选择图片
- Android保存图片到系统图库
- Android保存图片到系统图库
- 【HDU】5734 Acperience(2016 Multi-University Training Contest 2)
- Thinking in Java读书笔记
- 设置WebStrom 鼠标点击背景颜色
- 写入mysql的中文乱码问题
- List,Set,Map用法以及区别
- android打开系统图库终极适配
- 资源一:计算机视觉,机器学习方面的论文和算法代码
- 字符串验证Java工具类(未测试)
- 函数参数压栈从右到左
- 卷积神经网络(CNN)的参数优化方法
- 7 月21日_linux兴趣小组讲座:静态链接库&&系统编程基础(1)
- Spongebob and Joke
- 为RecyclerView添加item的点击事件(转载)
- java 下载网络中在文件 (未测试)