Android 4.4从图库选择图片并裁剪,由于系统版本不同导致Uri的bug的简单解决方式

来源:互联网 发布:淘宝立即购买是灰色的 编辑:程序博客网 时间:2024/05/16 14:26

做过Android换头像的都知道如何使用系统的方法选图片或者拍照换头像。有几个intent可以使用:

拍照:           new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
选取相册图片:    new Intent(Intent.ACTION_GET_CONTENT, null);          
               new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);


4.3或以下,选了图片之后,根据Uri来做处理,很多帖子都有了,我就不详细说了.主要是4.4,如果使用上面ACTION_PICK的原生方法来选图,返回的uri还是正常的,但如果用ACTION_GET_CONTENT的方法,返回的uri跟4.3是完全不一样的,4.3返回的是带文件路径的,而4.4返回的却是content://com.android.providers.media.documents/document/image:3951这样的,没有路径,只有图片编号的uri.这就导致接下来无法根据图片路径来裁剪的步骤了.


通常4.4得到的uri,需要以下方法来获取文件的路径

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;}/** * Get the value of the data column for this Uri. This is useful for * MediaStore Uris, and other file-based ContentProviders. * * @param context The context. * @param uri The Uri to query. * @param selection (Optional) Filter used in the query. * @param selectionArgs (Optional) Selection arguments used in the query. * @return The value of the _data column, which is typically a file path. */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;}/** * @param uri The Uri to check. * @return Whether the Uri authority is ExternalStorageProvider. */public static boolean isExternalStorageDocument(Uri uri) {    return "com.android.externalstorage.documents".equals(uri.getAuthority());}/** * @param uri The Uri to check. * @return Whether the Uri authority is DownloadsProvider. */public static boolean isDownloadsDocument(Uri uri) {    return "com.android.providers.downloads.documents".equals(uri.getAuthority());}/** * @param uri The Uri to check. * @return Whether the Uri authority is MediaProvider. */public static boolean isMediaDocument(Uri uri) {    return "com.android.providers.media.documents".equals(uri.getAuthority());}/** * @param uri The Uri to check. * @return Whether the Uri authority is Google Photos. */public static boolean isGooglePhotosUri(Uri uri) {    return "com.google.android.apps.photos.content".equals(uri.getAuthority());}

面代码看起来很麻烦。下面介绍个简单的方法处理不同版本的选择图库bug。

在onActivityResult里面打个断点看下返回的数据。首先是4.4系统以下,可以直接从extra中获得图片。


protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (data != null) {    Bundle extra = data.getExtras();    if (extra != null) {        Bitmap photo = null;        photo = (Bitmap) extra.get("data");    }

但是在4.4以上系统中,extra为空,返回图片的uri在data中



既然这个时候获得了图片uri,我们可以使用系统的方法从uri直接获取bitmap,不需要先把uri转化成path,然后获取文件然后解压。代码长这样:

photo = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data.getData());
这个时候获取的图片还没有剪裁,需要像拍照一样继续剪裁。

大功告成,这样不同版本的系统就可以使用相同的选取图片的代码了。


完整代码在这里:

public class ProfileActivity extends BaseActivity implements OnClickListener {        private final static int REQ_CAP_AVATAR = 1;//拍照    private final static int REQ_GET_AVATAR = 2;//选取照片    private final static int REQ_CROP = 3;//剪裁    private final static int REQ_UPDATE = 10;//上传        @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        if (resultCode == RESULT_OK) {            Intent result = getIntent();            if (requestCode == REQ_GET_AVATAR || requestCode == REQ_CROP) {                if (data != null) {                    Bitmap photo = null;                    Bundle extra = data.getExtras();                    if (extra != null) {                        photo = (Bitmap) extra.get("data");                    }                    if (photo == null && data.getData() != null) {                        try {                            photo = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data.getData());//这个时候图片没有进入剪裁,需要再次建材图片                            if (photo != null) {                                Intent intent = new Intent("com.android.camera.action.CROP");                                photo.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(MyApp.getMyCacheDir() + "avatar.jpg"));                                intent.setDataAndType(Uri.fromFile(new File(MyApp.getMyCacheDir() + "avatar.jpg")), "image/*");                                intent.putExtra("crop", "true");                                intent.putExtra("aspectX", 1);                                intent.putExtra("aspectY", 1);                                intent.putExtra("outputX", 100);                                intent.putExtra("outputY", 100);                                intent.putExtra("return-data", true);                                startActivityForResult(intent, REQ_CROP);                                return;                            }                        } catch (IOException e) {                            e.printStackTrace();                        }                    }                    if (photo != null) {                        try {                            photo.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(MyApp.getMyCacheDir() + "avatar.jpg"));                        } catch (FileNotFoundException e) {                            e.printStackTrace();                        }                    }                    mMasterIconView.setImageBitmap(photo);                    result.putExtra("photo", photo);                    doUpload();                }            } else if (requestCode == REQ_CAP_AVATAR) {                Intent intent = new Intent("com.android.camera.action.CROP");                intent.setDataAndType(Uri.fromFile(new File(MyApp.getMyCacheDir() + "avatar.jpg")), "image/*");                intent.putExtra("crop", "true");                intent.putExtra("aspectX", 1);                intent.putExtra("aspectY", 1);                intent.putExtra("outputX", 100);                intent.putExtra("outputY", 100);                intent.putExtra("return-data", true);                startActivityForResult(intent, REQ_CROP);            }            setResult(RESULT_OK, result);        }    }    @Override    public void onClick(View v) {        Intent intent;        switch (v.getId()) {            case R.id.pic_capture://拍照                if (ViewHelper.getAlpha(mPicPickMain) == 1f && mDetail != null) {                    Uri fileUri = Uri.fromFile(new File(MyApp.getMyCacheDir() + "avatar.jpg"));                    intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);                    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);                    startActivityForResult(intent, REQ_CAP_AVATAR);                    dismissPicPick();                }                break;            case R.id.pic_get://选择相册                if (ViewHelper.getAlpha(mPicPickMain) == 1f && mDetail != null) {                    intent = new Intent(Intent.ACTION_GET_CONTENT, null);                    new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);                    intent.setType("image/*");                    intent.putExtra("crop", "true");                    intent.putExtra("aspectX", 1);                    intent.putExtra("aspectY", 1);                    intent.putExtra("outputX", 100);                    intent.putExtra("outputY", 100);                    intent.putExtra("return-data", true);                    startActivityForResult(intent, REQ_GET_AVATAR);                    dismissPicPick();                }                break;        }    }    //上传图片    private void doUpload() {}        }





1 2
原创粉丝点击