最近在做一个需要上传拍照的APP,上传的时候因为是小图片,但是需求提了要点击可预览大图,一看大图,被吓到了,根本看不清楚,大图中的具体内容。原因是通过MediaStore.ACTION_IMAGE_CAPTURE方式直接去调用相机,在onactivityresult()方法中返回的结果data.getExtras().get(“data”)这种方式去获取的图片。当时大概测了一下,bitmap的大小在12K左右(我用的4.0的老手机测得,其他的不太清楚)。然而用相机拍摄的图片大小在手机相册中查看大约在2M左右,这完全不是一个级别。当然这个问题不是我首先发现的,是因为测试那边发现我穿的照片质量不清晰(尴尬的一笑)。
于是,我就去查了一下,原来调用系统相机去获取data时获取到的只是缩略图,如果想要查看大图,需要将拍照得到的原图则保存到手机中,然后再去读取。
下面我们就来看一下具体实现
- 权限以及版本兼容问题
调用相机权限肯定少不了,不仅仅要考虑到动态权限的请求,还要考虑到Android7.0以后对Uri一些操作,如果不做特别处理的话也会报异常(注意点)。我们先来做7.0版本之前的功能,直接上代码:
// 获取SD卡路径
mFilePath = Environment.getExternalStorageDirectory().getPath();
// 保存图片的文件名
mFilePath = mFilePath + "/" + "mytest.png";
// 指定拍照意图
Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 加载路径图片路径
Uri mUri = Uri.fromFile(new File(mFilePath));
// 指定存储路径,这样就可以保存原图了
openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mUri);
startActivityForResult(openCameraIntent, TAKE_PICTURE);
在onactivityresult()方法中做对应的处理:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case TAKE_PICTURE:
try {
// 获取输入流
is = new FileInputStream(mFilePath);
// 把流解析成bitmap,此时就得到了清晰的原图
Bitmap bitmap = BitmapFactory.decodeStream(is);
//接下来就可以展示了(或者做上传处理)
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 关闭流
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
做到这里,图片的清晰度应该没问题了,但是如果你没有测试7.0以上的版本的话,那肯定不会发现下面的问题:
FATAL EXCEPTION: main android.os.FileUriExposedException: file:///storage/emulated/0/photo.png expos
这个问题怎么解决呢,所以我们在写调用拍照的代码的时候就要考虑到这个问题,因此只是对上面的第一块的代码进行一些更改就可以了,具体如下:
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
takePhotoBiggerThan7((new File(mFilePath)).getAbsolutePath());
}else {
// 指定拍照意图
Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 加载路径图片路径
Uri mUri = Uri.fromFile(new File(mFilePath));
// 指定存储路径,这样就可以保存原图了
openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mUri);
startActivityForResult(openCameraIntent, TAKE_PICTURE);
}
private void takePhotoBiggerThan7(String absolutePath) {
Uri mCameraTempUri;
try {
ContentValues values = new ContentValues(1);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
values.put(MediaStore.Images.Media.DATA, absolutePath);
mCameraTempUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if (mCameraTempUri != null) {
intent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraTempUri);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
}
startActivityForResult(intent, TAKE_PICTURE);
} catch (Exception e) {
e.printStackTrace();
}
}
到此,拍照得到的图片不清晰问题就OK了,这里就不上源码了,我想贴的已经够仔细了,如果有什么问题,大家可以指正,谢谢!