Android 4.4从图库选择图片,获取图片路径并裁剪

原文章地址:Android 4.4从图库选择图片,获取图片路径并裁剪

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

[java] view plaincopy在CODE上查看代码片派生到我的代码片

01. Intent intent=new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

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

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

这个方法就是

[java] view plaincopy在CODE上查看代码片派生到我的代码片

01. Intent intent=new Intent(Intent.ACTION_GET_CONTENT);//ACTION_OPEN_DOCUMENT

02. intent.addCategory(Intent.CATEGORY_OPENABLE);

03. intent.setType("image/jpeg");

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

05.        startActivityForResult(intent, SELECT_PIC_KITKAT);

06. }else{

07.        startActivityForResult(intent, SELECT_PIC);

08. }

为什么要分开不同版本呢?其实在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 plaincopy在CODE上查看代码片派生到我的代码片

01. Caused by: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.media.MediaDocumentsProvider from ProcessRecord{437b5d88 9494:com.google.android.gallery3d/u0a20} (pid=9494, uid=10020) requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS

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

[java] view plaincopy在CODE上查看代码片派生到我的代码片

01. public static String getPath(final Context context, final Uri uri) {

02.

03.    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

04.

05.    // DocumentProvider

06.    if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {

07.        // ExternalStorageProvider

08.        if (isExternalStorageDocument(uri)) {

09.            final String docId = DocumentsContract.getDocumentId(uri);

10.            final String[] split = docId.split(":");

11.            final String type = split[0];

12.

13.            if ("primary".equalsIgnoreCase(type)) {

14.                return Environment.getExternalStorageDirectory() + "/" + split[1];

15.            }

16.

17.            // TODO handle non-primary volumes

18.        }

19.        // DownloadsProvider

20.        else if (isDownloadsDocument(uri)) {

21.

22.            final String id = DocumentsContract.getDocumentId(uri);

23.            final Uri contentUri = ContentUris.withAppendedId(

24.                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

25.

26.            return getDataColumn(context, contentUri, null, null);

27.        }

28.        // MediaProvider

29.        else if (isMediaDocument(uri)) {

30.            final String docId = DocumentsContract.getDocumentId(uri);

31.            final String[] split = docId.split(":");

32.            final String type = split[0];

33.

34.            Uri contentUri = null;

35.            if ("image".equals(type)) {

36.                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

37.            } else if ("video".equals(type)) {

38.                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;

39.            } else if ("audio".equals(type)) {

40.                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;

41.            }

42.

43.            final String selection = "_id=?";

44.            final String[] selectionArgs = new String[] {

45.                    split[1]

46.            };

47.

48.            return getDataColumn(context, contentUri, selection, selectionArgs);

49.        }

50.    }

51.    // MediaStore (and general)

52.    else if ("content".equalsIgnoreCase(uri.getScheme())) {

53.

54.        // Return the remote address

55.        if (isGooglePhotosUri(uri))

56.            return uri.getLastPathSegment();

57.

58.        return getDataColumn(context, uri, null, null);

59.    }

60.    // File

61.    else if ("file".equalsIgnoreCase(uri.getScheme())) {

62.        return uri.getPath();

63.    }

64.

65.    return null;

66. }

67.

68. /**

69.  * Get the value of the data column for this Uri. This is useful for

70.  * MediaStore Uris, and other file-based ContentProviders.

71.  *

72.  * @param context The context.

73.  * @param uri The Uri to query.

74.  * @param selection (Optional) Filter used in the query.

75.  * @param selectionArgs (Optional) Selection arguments used in the query.

76.  * @return The value of the _data column, which is typically a file path.

77.  */

78. public static String getDataColumn(Context context, Uri uri, String selection,

79.        String[] selectionArgs) {

80.

81.    Cursor cursor = null;

82.    final String column = "_data";

83.    final String[] projection = {

84.            column

85.    };

86.

87.    try {

88.        cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,

89.                null);

90.        if (cursor != null && cursor.moveToFirst()) {

91.            final int index = cursor.getColumnIndexOrThrow(column);

92.            return cursor.getString(index);

93.        }

94.    } finally {

95.        if (cursor != null)

96.            cursor.close();

97.    }

98.    return null;

99. }

100.

101.

102. /**

103.  * @param uri The Uri to check.

104.  * @return Whether the Uri authority is ExternalStorageProvider.

105.  */

106. public static boolean isExternalStorageDocument(Uri uri) {

107.    return "com.android.externalstorage.documents".equals(uri.getAuthority());

108. }

109.

110. /**

111.  * @param uri The Uri to check.

112.  * @return Whether the Uri authority is DownloadsProvider.

113.  */

114. public static boolean isDownloadsDocument(Uri uri) {

115.    return "com.android.providers.downloads.documents".equals(uri.getAuthority());

116. }

117.

118. /**

119.  * @param uri The Uri to check.

120.  * @return Whether the Uri authority is MediaProvider.

121.  */

122. public static boolean isMediaDocument(Uri uri) {

123.    return "com.android.providers.media.documents".equals(uri.getAuthority());

124. }

125.

126. /**

127.  * @param uri The Uri to check.

128.  * @return Whether the Uri authority is Google Photos.

129.  */

130. public static boolean isGooglePhotosUri(Uri uri) {

131.    return "com.google.android.apps.photos.content".equals(uri.getAuthority());

132. }

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

昨天发现了个bug,如果在4.4上面不用"图片"来选,用"图库"来选,就会无法读取到图片路径,所以只需要加个判断,如果是用旧方式来选,就用旧方式来读,就是如果

DocumentsContract.isDocumentUri(context, uri) 返回false的话,就用旧的方式

[java] view plaincopy在CODE上查看代码片派生到我的代码片

01. public static String selectImage(Context context,Intent data){

02.        Uri selectedImage = data.getData();

03. //      Log.e(TAG, selectedImage.toString());

04.        if(selectedImage!=null){

05.            String uriStr=selectedImage.toString();

06.            String path=uriStr.substring(10,uriStr.length());

07.            if(path.startsWith("com.sec.android.gallery3d")){

08.                Log.e(TAG, "It's auto backup pic path:"+selectedImage.toString());

09.                return null;

10.            }

11.        }

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

13.        Cursor cursor = context.getContentResolver().query(selectedImage,filePathColumn, null, null, null);

14.        cursor.moveToFirst();

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

16.        String picturePath = cursor.getString(columnIndex);

17.        cursor.close();

18.        return picturePath;

19.    }

这样就OK的了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容