Android从相册以及拍照选取照片,然后裁剪保存遇到的问题

来源:互联网 发布:淘宝视频自动播放关闭 编辑:程序博客网 时间:2024/06/06 07:27

对于从拍照或者相册选取图片然后进行裁剪保存的需求,大部分APP都会遇到,下面是简单地使用方法。

1.使用隐式Intent启动相机

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);startActivityForResult(intent, 1);

2.从图库中选择照片
Intent intent = new Intent(Intent.ACTION_PICK,null);intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,"image/*");startActivityForResult(intent, 2)
3,在onActivityResult()方法中获取返回的数据
public void onActivityResult(int requestCode, int resultCode, final Intent data) {        super.onActivityResult(requestCode, resultCode, data);if(resultCode == RESULT_OK){if(requestCode==1){Uri uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "/" + fileName));cutImage(uri);}else if(requestCode==2){if(data != null){Uri uri=data.getData();cutImage(uri);}}else if(requestCode==REQUEST_TO_PHOTOCUTED){Bitmap bitmap = data.getParcelableExtra("data");}}}
4.剪切方法
public void cutImage(Uri uri) {        Intent intent = new Intent("com.android.camera.action.CROP");        intent.setDataAndType(uri,"image/*");        //下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪        intent.putExtra("crop", "true");        // aspectX aspectY 是宽高的比例        intent.putExtra("aspectX", 1);        intent.putExtra("aspectY", 1);        // outputX outputY 是裁剪图片宽高        intent.putExtra("outputX", 250);//剪裁后X的像素        intent.putExtra("outputY", 350);//剪裁后Y的像素//      intent.putExtra("outputFormat", "JPEG");// 返回格式//      是否去除面部检测, 如果你需要特定的比例去裁剪图片,那么这个一定要去掉,因为它会破坏掉特定的比例。//      intent.putExtra("noFaceDetection", true);//      是否要返回值。 一般都要。我第一次忘加了,总是取得空值        intent.putExtra("return-data", true);        startActivityForResult(intent, REQUEST_TO_PHOTOCUTED);    }
上面是大家经常用的拍照剪切的方法,但是,这样写在部分Android手机上就会卡死,崩溃。
原因是在剪切方法中设置了如下属性:intent.putExtra("return-data", true);
通过Intent中的data来传递,当数据过大,在部分手机上时就崩了,(公司一个360手机,这样写总是崩溃)
解决的方法:通过uri来传递。
此时剪切方法中cutImage(Uri uri)中:

修改:

intent.putExtra("return-data", false);

增加:

intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());intent.putExtra("noFaceDetection", true);intent.putExtra("output",Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "/cutphone")));
在onActivityResult(int requestCode, int resultCode, final Intent data)方法数据回调中,通过uri拿到Bitmap
if(requestCode==REQUEST_TO_PHOTOCUTED){Bitmap bitmap = MediaStore.Images.Media.getBitmap(baseContext.getContentResolver(),uri));}
这样修改后,有的手机还是会出现问题,上网查看资料Android7.0后,以前适用的File Uri需要更改为Content Uri。 Android 框架强制执行了 StrictMode API 政策禁止向你的应用外公开 file:// URI。  如果一项包含文件 file:// URI类型 的 Intent 离开你的应用,应用失败,并出现 FileUriExposedException 异常,如调用系统相机拍照,或裁切照片。 这里我们可以使用 content:// URI类型的Uri,网上有好多的方法都是使用FileProvider类。可以去网上查看,这里我使用的一个方法,把File Uri换成Content Uri
public static Uri getImageContentUri(Context context, File imageFile) { String filePath = imageFile.getAbsolutePath(); Cursor cursor = context.getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[] { MediaStore.Images.Media._ID }, MediaStore.Images.Media.DATA + "=? ", new String[] { filePath }, null); if (cursor != null && cursor.moveToFirst()) { int id = cursor.getInt(cursor .getColumnIndex(MediaStore.MediaColumns._ID)); Uri baseUri = Uri.parse("content://media/external/images/media"); return Uri.withAppendedPath(baseUri, "" + id); } else { if (imageFile.exists()) { ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DATA, filePath); return context.getContentResolver().insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } else { return null; } }}
通过这个方法。把从相册,拍照获取的uri转换成Content Uri,再进行剪切,然后保存在File Uri中,在回调数据中拿到;

具体代码:

public void onActivityResult(int requestCode, int resultCode, final Intent data) {        super.onActivityResult(requestCode, resultCode, data);if(resultCode == RESULT_OK){if(requestCode==1){Uri uri = getImageContentUri(this,new File(Environment.getExternalStorageDirectory(), "/" + fileName))cutImage(uri);}else if(requestCode==2){if(data != null){Uri uri=getImageContentUri(baseContext,new File(BitmapHelper.getImageAbsolutePath(baseContext,data.getData())));cutImage(uri);}}else if(requestCode==REQUEST_TO_PHOTOCUTED){Bitmap bitmap = MediaStore.Images.Media.getBitmap(baseContext.getContentResolver(),Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "/cutphone")));}}

public void cutImage(Uri uri) {        Intent intent = new Intent("com.android.camera.action.CROP");        intent.setDataAndType(uri,"image/*");        intent.putExtra("crop", "true");        intent.putExtra("aspectX", 1);        intent.putExtra("aspectY", 1);        intent.putExtra("outputX", 250);//剪裁后X的像素        intent.putExtra("outputY", 350);//剪裁后Y的像素        intent.putExtra("output",Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "/cutphone"))); //保存路径me        intent.putExtra("return-data", false);        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());        intent.putExtra("noFaceDetection", true);        startActivityForResult(intent, REQUEST_TO_PHOTOCUTED);    }
 
阅读全文
1 0