对于从拍照或者相册选取图片然后进行裁剪保存的需求,大部分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);
}