打开相机通常来讲有两种方式,一种是本身初始化相机,调用Camera组件,相对来讲这种比较复杂,须要作的工做也比较多,还有一种是调用相机的隐式Intent打开相机,打开相机选择图片这种需求其实调用隐式Intent就能够了,不必本身初始化camera对象。java

下面是介绍的是如何打开camera相机;android

/** * 初始化相机控件 */
private void openCamera() {
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
// 部分机型更改了action的值,这里尽可能使用系统定义的常量
Intent getImageByCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (TextUtils.isEmpty(H5Constant.bigPicPath)) {
H5Constant.bigPicPath = SysConfig.SD_IMAGE_PATH + H5Constant.tempImage;
}
// 将相机所拍摄图片保存在临时目录
getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(H5Constant.bigPicPath)));
// 添加隐士intent跳转的判断,若没有对应的activity,则不作处理
if (getImageByCamera.resolveActivity(h5Activity.getPackageManager()) != null) {
h5Activity.startActivityForResult(getImageByCamera, H5Constant.h5CameraCode);
}
} else {
Toast.makeText(h5Activity, "请确认已经插入SD卡", Toast.LENGTH_LONG).show();
}
}

首先是判断SD卡的状态,而后建立打开相机的Intent对象,同时设置参数将相机拍照的相片保存在指定目录用于咱们后期的裁剪,旋转,压缩等操做;

这里有一个须要注意的地方时,在使用友盟测试的时候,部分机型调用以下代码会报错:web

Intent getImageByCamera = new Intent("android.media.action.IMAGE_CAPTURE");

这是因为不一样的系统修改的隐式intent的字符串值….,因此咱们尽可能使用系统的常量,并增长判断,该intent是否有对应的activity:ide

if (getImageByCamera.resolveActivity(h5Activity.getPackageManager()) != null) {
h5Activity.startActivityForResult(getImageByCamera, H5Constant.h5CameraCode);
}

若存在则打开对应的activity;

这时候会打开相机,咱们能够选择拍照,拍照完成以后的处理逻辑,咱们须要回调当前activity的onActivityResult方法:svg

// 打开相机解析图片
if (requestCode == H5Constant.h5CameraCode && resultCode == RESULT_OK) {
new Thread(new Runnable() {
@Override
public void run() {
Bitmap bitmapTemp = null;
if (TextUtils.isEmpty(H5Constant.bigPicPath)) {
H5Constant.bigPicPath = SysConfig.SD_IMAGE_PATH + H5Constant.tempImage;
}
if (H5Constant.bigPicPath != null) {
// 压缩图片的宽高
int photoWidth = 320, photoHeight = 480;
bitmapTemp = BitmapUtils.getInSampleBitmap(H5Constant.bigPicPath, photoWidth, photoHeight);
}
if (bitmapTemp != null) {
// 判断图片是否须要旋转角度,若须要的话则旋转
bitmapTemp = BitmapUtils.rotateBitmapByDegree(bitmapTemp, BitmapUtils.getBitmapDegree(H5Constant.bigPicPath));
if (bitmapTemp != null) {
if (TextUtils.isEmpty(H5Constant.picPath)) {
H5Constant.picPath = SysConfig.SD_IMAGE_PATH + H5Constant.compressImage;
}
BitmapUtils.saveImage(bitmapTemp, H5Constant.picPath);
try {
if (!TextUtils.isEmpty(H5Constant.cameraCallback)) {
...
}
} catch (Exception e) {
e.printStackTrace();
}
if (bitmapTemp != null && !bitmapTemp.isRecycled()) {
bitmapTemp.recycle();
}
}
}
}
}).start();

这里须要注意一个地方:咱们须要判断resultCode是否为RESULT_OK,当resultCode为RESULT_OK时,拍照成功,若resultCode不是RESULT_OK则说明用户并无拍照而是直接返回,这种状况下咱们暂时不作任何处理;post

(一)因为裁剪,旋转,压缩操做比较多,因此暂时在子线程中执行;

(二)裁剪功能测试

if (H5Constant.bigPicPath != null) {
// 压缩图片的宽高
int photoWidth = 320, photoHeight = 480;
bitmapTemp = BitmapUtils.getInSampleBitmap(H5Constant.bigPicPath, photoWidth, photoHeight);
}

压缩比例为320 * 480spa

public static Bitmap getInSampleBitmap(String filePath, int width, int height) {
// 将dp转换为px
int widthNeed = (int) (width * DisplayUtil.density);
int heightNeed = (int) (height * DisplayUtil.density);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
int originalWidth = options.outWidth;
int originalHight = options.outHeight;
// 获取裁剪比例
int inSample;
if (originalWidth >= originalHight) {
inSample = getInsampleSize(originalWidth, widthNeed);
} else {
inSample = getInsampleSize(originalHight, heightNeed);
}
options.inJustDecodeBounds = false;
options.inSampleSize = inSample;
// 执行裁剪操做
return BitmapFactory.decodeFile(filePath, options);

(三)旋转操做线程

// 判断图片是否须要旋转角度,若须要的话则旋转
bitmapTemp = BitmapUtils.rotateBitmapByDegree(bitmapTemp, BitmapUtils.getBitmapDegree(H5Constant.bigPicPath));
获取图片的旋转角度code
/** * 读取图片的旋转的角度 * *@param path 图片绝对路径 *@return 图片的旋转角度 */
public static int getBitmapDegree(String path) {
int degree = 0;
try {
// 从指定路径下读取图片,并获取其EXIF信息
ExifInterface exifInterface = new ExifInterface(path);
// 获取图片的旋转信息
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}

旋转图片

/** * 将图片按照某个角度进行旋转 * *@param bm 须要旋转的图片 *@param degree 旋转角度 *@return 旋转后的图片 */
public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
Bitmap returnBm = null;
// 根据旋转角度,生成旋转矩阵
Matrix matrix = new Matrix();
matrix.postRotate(degree);
try {
// 将原始图片按照旋转矩阵进行旋转,并获得新的图片
returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
} catch (OutOfMemoryError e) {
}
if (returnBm == null) {
returnBm = bm;
}
if (bm != null && bm != returnBm) {
bm.recycle();
}
return returnBm;
}

(四)压缩图片

BitmapUtils.saveImage(bitmapTemp, H5Constant.picPath);
压缩图片并保存
/** * 保存并压缩图片 * *@param photo *@param spath *@return */
public static boolean saveImage(Bitmap photo, String spath) {
try {
File mPhotoFile = new File(spath);
if (!mPhotoFile.exists()) {
mPhotoFile.createNewFile();
}
photo = BitmapUtils.getInSampleBitmapByBitmap(photo);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(spath, false));
photo.compress(Bitmap.CompressFormat.JPEG, 50, bos);
bos.flush();
bos.close();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}

1)采用50%的压缩比例

2)经测试在1300W像素的手机上(主流手机后置摄像头目前均未1300W)

原始图片

像素:4208 * 2368

大小:1.32M

旋转角度:0度;

通过裁剪,旋转,压缩以后 像素:1052 * 592 大小:51k 旋转角度:0度; 3)须要注意的是通过压缩以后图片信息所保存的Exif信息丢失