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

[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的了




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

更多相关文章

  1. 更改android AVD模拟器创建路径位置
  2. android-HttpClient上传信息(包括图片)到服务端
  3. android修改图片(修改图片大小,图片旋转,图片平移)
  4. android bitmap out of memory总结、心得
  5. MyAdapter
  6. Android创建本地文件夹、创建本地文件以及访问本地文件
  7. Android(安卓)Studio 在run时报的异常 Failed to run command fi
  8. 运用开源 achartengine 绘制android端的折线图片,多表显示
  9. 用gdb调试 android webkit

随机推荐

  1. Android(安卓)页面惯性回弹效果,Nested接
  2. Android(安卓)M 新的运行时权限开发者需
  3. Android教父高焕堂:开源只是手段,开放才是
  4. [android与open source不得不说的事]Andr
  5. 如何发布你的Android应用程序
  6. Oracle vs. Google 訴訟最新發展,Sun CEO
  7. 使用android快速开发框架afinal 开发andr
  8. Android中的实体类的正确用法
  9. Android进阶知识树——Android系统的启动
  10. Android设计模式-原型模式