Android 调用系统相机拍照
在这次的开发中用到了拍照上传图片的功能,还好 Android 中调用系统相机很方便,代码如下:
cameraBtn.setOnClickListener(new OnClickListener() {
public void onClick() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, TAKE_PHOTO_REQUEST_CODE);
}
});
获取拍照后图片数据,代码如下:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case TAKE_PHOTO_REQUEST_CODE:
if(data!=null){
Bundle extras = data.getExtras();
Bitmap bmp = (Bitmap) extras.get("data");
imageView.setImageBitmap(bmp); //设置照片现实在界面上
}
break;
}
}
此时便遇到了问题,测试发现不同手机调用系统相机拍照时,有些并不会把照片存储起来,导致返回时无法获取照片数据,使用 Log 打印数据之后发现 Bitmap bmp = (Bitmap) extras.get("data"); 处出现异常。Android 的兼容性真是一个头大的难题,但是问题依然是要解决,google 了有了解决方案。就是拍照时会把数据指定存储在 SDcard 上,然后读取 SDcard 上的图片数据显示在 ImageView 上。下面就看下解决问题的代码:
cameraBtn.setOnClickListener(new OnClickListener() {
public void onClick() {
if (!isHasSdCard()) {
Helper.showToast(ctx, R.string.sdcard_no_avaiable);
return;
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 指定存储照片的路径
Uri imageUri = Uri.fromFile(getTempImage());
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, TAKE_PHOTO_REQUEST_CODE);
}
});
上面代码会指定调用系统相机拍照时图片的存储路径,其中指定了一个临时文件 temp.jpg 来存储。
public static File getTempImage() {
if (android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED)) {
File tempFile = new File(Environment.getExternalStorageDirectory(), "temp.jpg");
try {
tempFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
return tempFile;
}
return null;
}
这时的 onActivityResult 的方法是下面这样的:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case TAKE_PHOTO:
if (resultCode == RESULT_OK) {
Bitmap bmp = BitmapFactory.decodeFile(getTempImage().getPath());
if (null != bmp) {
postImage.setImageBitmap(bmp);
}
}
break;
}
}
兼容性问题终于解决了,不过不幸的是新的问题又出现了。
由于目前 Android 手机的相机像素普遍已经比较高了,拍出来的照片可能都会达到 1-2M,把这么大的一张图片加载进内存里肯定会报出 OOM 错误。即:
Bitmap bmp = BitmapFactory.decodeFile(getTempImage().getPath());
这行代码会报出内存不足的错误。所以解决方案是在拍照后返回的 bitmap 必须要经过压缩,然后加载进内存从而渲染出来才不会报出内存不足的错误。下面就看代码:
public static Bitmap getScaleBitmap(Context ctx, String filePath) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, opt);
int bmpWidth = opt.outWidth;
int bmpHeght = opt.outHeight;
WindowManager windowManager = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();
opt.inSampleSize = 1;
if (bmpWidth > bmpHeght) {
if (bmpWidth > screenWidth)
opt.inSampleSize = bmpWidth / screenWidth;
} else {
if (bmpHeght > screenHeight)
opt.inSampleSize = bmpHeght / screenHeight;
}
opt.inJustDecodeBounds = false;
bmp = BitmapFactory.decodeFile(filePath, opt);
return bmp;
}
上述代码的关键在于 inJustDecodeBounds 属性。如果设置 inJustDecodeBounds 为 true,仍可以获取到 bitmap 信息,但完全不用分配内存,因为没有获取像素,所以我们可以利用得到的 Bitmap 的大小,重新压缩图片,然后在内存中生成一个更小的 Bitmap,这样即便是一个 4MB 的 JPG,我们也可以随心所欲地把他压缩到任意大小,从而节省了内存。
下面看下更改后的代码:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case TAKE_PHOTO:
if (resultCode == RESULT_OK) {
Bitmap bmp = getScaleBitmap(ctx, getTempImage().getPath());
if (null != bmp) {
postImage.setImageBitmap(bmp);
}
}
break;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论