转至http://blog.csdn.net/tempersitu/article/details/20557383

最近在做一个从图库选择图片或拍照,然后裁剪的功能.本来是没问题的,一直在用

[java] view plain copy
  1. Intentintent=newIntent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

的方式来做,是调用系统图库来做,但是发现如果有图片是同步到google相册的话,图库里面能看到一个auto backup的目录,点进去选图片的话是无法获取到图片的路径的.因为那些图片根本就不存在于手机上.然后看到无论是百度贴吧,Instagram,或者还有些会选取图片做修改的app,都是用一个很漂亮的图片选择器(4.4以上,4.3的还是用系统旧的图库).

而这个图片选择器可以屏蔽掉那个auto backup的目录.所以就开始打算用这个图片选择器来选图片了.
这个方法就是

[java] view plain copy
  1. Intentintent=newIntent(Intent.ACTION_GET_CONTENT);//ACTION_OPEN_DOCUMENT
  2. intent.addCategory(Intent.CATEGORY_OPENABLE);
  3. intent.setType("image/jpeg");
  4. if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.KITKAT){
  5. startActivityForResult(intent,SELECT_PIC_KITKAT);
  6. }else{
  7. startActivityForResult(intent,SELECT_PIC);
  8. }

为什么要分开不同版本呢?其实在4.3或以下可以直接用ACTION_GET_CONTENT的,在4.4或以上,官方建议用ACTION_OPEN_DOCUMENT,但其实都不算太大区别,区别是他们返回的Uri,那个才叫大区别.这就是困扰了我一整天的问题所在了.

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.这就导致接下来无法根据图片路径来裁剪的步骤了.

还好找了很多方法,包括加权限啊什么的,中间还试过用一些方法,自己的app没崩溃,倒是让系统图库崩溃了,引发了java.lang.SecurityException.

[java] view plain copy
  1. Causedby:java.lang.SecurityException:PermissionDenial:openingprovidercom.android.providers.media.MediaDocumentsProviderfromProcessRecord{437b5d889494:com.google.android.gallery3d/u0a20}(pid=9494,uid=10020)requiresandroid.permission.MANAGE_DOCUMENTSorandroid.permission.MANAGE_DOCUMENTS


看来4.4的系统还是有些bug.重点来了,4.4得到的uri,需要以下方法来获取文件的路径

[java] view plain copy
  1. publicstaticStringgetPath(finalContextcontext,finalUriuri){
  2. finalbooleanisKitKat=Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT;
  3. //DocumentProvider
  4. if(isKitKat&&DocumentsContract.isDocumentUri(context,uri)){
  5. //ExternalStorageProvider
  6. if(isExternalStorageDocument(uri)){
  7. finalStringdocId=DocumentsContract.getDocumentId(uri);
  8. finalString[]split=docId.split(":");
  9. finalStringtype=split[0];
  10. if("primary".equalsIgnoreCase(type)){
  11. returnEnvironment.getExternalStorageDirectory()+"/"+split[1];
  12. }
  13. //TODOhandlenon-primaryvolumes
  14. }
  15. //DownloadsProvider
  16. elseif(isDownloadsDocument(uri)){
  17. finalStringid=DocumentsContract.getDocumentId(uri);
  18. finalUricontentUri=ContentUris.withAppendedId(
  19. Uri.parse("content://downloads/public_downloads"),Long.valueOf(id));
  20. returngetDataColumn(context,contentUri,null,null);
  21. }
  22. //MediaProvider
  23. elseif(isMediaDocument(uri)){
  24. finalStringdocId=DocumentsContract.getDocumentId(uri);
  25. finalString[]split=docId.split(":");
  26. finalStringtype=split[0];
  27. UricontentUri=null;
  28. if("image".equals(type)){
  29. contentUri=MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
  30. }elseif("video".equals(type)){
  31. contentUri=MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
  32. }elseif("audio".equals(type)){
  33. contentUri=MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
  34. }
  35. finalStringselection="_id=?";
  36. finalString[]selectionArgs=newString[]{
  37. split[1]
  38. };
  39. returngetDataColumn(context,contentUri,selection,selectionArgs);
  40. }
  41. }
  42. //MediaStore(andgeneral)
  43. elseif("content".equalsIgnoreCase(uri.getScheme())){
  44. //Returntheremoteaddress
  45. if(isGooglePhotosUri(uri))
  46. returnuri.getLastPathSegment();
  47. returngetDataColumn(context,uri,null,null);
  48. }
  49. //File
  50. elseif("file".equalsIgnoreCase(uri.getScheme())){
  51. returnuri.getPath();
  52. }
  53. returnnull;
  54. }
  55. /**
  56. *GetthevalueofthedatacolumnforthisUri.Thisisusefulfor
  57. *MediaStoreUris,andotherfile-basedContentProviders.
  58. *
  59. *@paramcontextThecontext.
  60. *@paramuriTheUritoquery.
  61. *@paramselection(Optional)Filterusedinthequery.
  62. *@paramselectionArgs(Optional)Selectionargumentsusedinthequery.
  63. *@returnThevalueofthe_datacolumn,whichistypicallyafilepath.
  64. */
  65. publicstaticStringgetDataColumn(Contextcontext,Uriuri,Stringselection,
  66. String[]selectionArgs){
  67. Cursorcursor=null;
  68. finalStringcolumn="_data";
  69. finalString[]projection={
  70. column
  71. };
  72. try{
  73. cursor=context.getContentResolver().query(uri,projection,selection,selectionArgs,
  74. null);
  75. if(cursor!=null&&cursor.moveToFirst()){
  76. finalintindex=cursor.getColumnIndexOrThrow(column);
  77. returncursor.getString(index);
  78. }
  79. }finally{
  80. if(cursor!=null)
  81. cursor.close();
  82. }
  83. returnnull;
  84. }
  85. /**
  86. *@paramuriTheUritocheck.
  87. *@returnWhethertheUriauthorityisExternalStorageProvider.
  88. */
  89. publicstaticbooleanisExternalStorageDocument(Uriuri){
  90. return"com.android.externalstorage.documents".equals(uri.getAuthority());
  91. }
  92. /**
  93. *@paramuriTheUritocheck.
  94. *@returnWhethertheUriauthorityisDownloadsProvider.
  95. */
  96. publicstaticbooleanisDownloadsDocument(Uriuri){
  97. return"com.android.providers.downloads.documents".equals(uri.getAuthority());
  98. }
  99. /**
  100. *@paramuriTheUritocheck.
  101. *@returnWhethertheUriauthorityisMediaProvider.
  102. */
  103. publicstaticbooleanisMediaDocument(Uriuri){
  104. return"com.android.providers.media.documents".equals(uri.getAuthority());
  105. }
  106. /**
  107. *@paramuriTheUritocheck.
  108. *@returnWhethertheUriauthorityisGooglePhotos.
  109. */
  110. publicstaticbooleanisGooglePhotosUri(Uriuri){
  111. return"com.google.android.apps.photos.content".equals(uri.getAuthority());
  112. }

这样,就可以在4.4上用漂亮的图片选择器,选到我们想要的文件,又不会出问题了.

昨天发现了个bug,如果在4.4上面不用"图片"来选,用"图库"来选,就会无法读取到图片路径,所以只需要加个判断,如果是用旧方式来选,就用旧方式来读,就是如果
DocumentsContract.isDocumentUri(context, uri) 返回false的话,就用旧的方式

[java] view plain copy
  1. publicstaticStringselectImage(Contextcontext,Intentdata){
  2. UriselectedImage=data.getData();
  3. //Log.e(TAG,selectedImage.toString());
  4. if(selectedImage!=null){
  5. StringuriStr=selectedImage.toString();
  6. Stringpath=uriStr.substring(10,uriStr.length());
  7. if(path.startsWith("com.sec.android.gallery3d")){
  8. Log.e(TAG,"It'sautobackuppicpath:"+selectedImage.toString());
  9. returnnull;
  10. }
  11. }
  12. String[]filePathColumn={MediaStore.Images.Media.DATA};
  13. Cursorcursor=context.getContentResolver().query(selectedImage,filePathColumn,null,null,null);
  14. cursor.moveToFirst();
  15. intcolumnIndex=cursor.getColumnIndex(filePathColumn[0]);
  16. StringpicturePath=cursor.getString(columnIndex);
  17. cursor.close();
  18. returnpicturePath;
  19. }


这样就OK的了

更多相关文章

  1. Android实现图片单点旋转缩放保存-仿百度魔图
  2. build/envsetup.sh简记
  3. Android(安卓)易忘部分
  4. android获取本地图片或拍照图片
  5. Android学习札记47:TextView显示Html类解析的网页和图片及自定义
  6. Android(安卓)图像系列: 图片的压缩
  7. Android(安卓)实现简单的画画版一
  8. Android(安卓)选择图片、上传图片之ImagePicker
  9. MonkeyRunner进坑——errors importing other modules

随机推荐

  1. android listview让分割线消失
  2. Android获取屏幕宽高的方法
  3. android 创建菜单列表及其事件
  4. Android curl的下载编译和使用
  5. [Android]当Activity启动模式为singleTas
  6. 编译可在Android上运行的可执行文件:C/C++
  7. android开源代码站开通啦!
  8. Android SearchView结合Filter实现列表检
  9. Android画图
  10. Android(安卓)自定义ProgressDialog