一、调用第三方相机进行拍照
1、需要添加调用相机和外部存储的权限
<span style="font-size:14px;"><uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/></span>
需要注意的是安卓6.0后使用相机等涉及隐私的权限需要在代码内在申明,可通过以下方法:
<span style="font-size:14px;">if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, CAMERA_JAVA_REQUEST_CODE);
}</span>
2、使用Intent启动第三方相机
可以通过startActivityForResult获取到拍完照片的结果信息。
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, getUri());
startActivityForResult(intent, CAMERA_REQUEST_CODE);
其中需要的到给定一个图片保存的Uri
private Uri getUri() {
return Uri.fromFile(getFile());
}
/**
* 该方法用于获取指定路径 和 名字 的file
* @return
*/
private File getFile() {
File filePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "CameraDemo");
if (!filePath.exists()) {
filePath.mkdirs();
}
//将图片保存的名字设置为当前拍照的时间
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String name = format.format(new Date());
File file = new File(filePath.getPath() + File.separator + name + ".jpg");
return file;
}
3、重写
onActivityResult获取拍照后返回的信息
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Log.d("print", "拍照成功");
}
}
}
二、使用camera进行拍照
1、需要借助SurfaceView来显示,进行拍照预览。在布局文件中添加SurfaceView。
2、对相应权限进行设置,同调用第三方相机。
3、为SurfaceView设置回调
sf_camera.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
/**
* 请求权限是一个异步任务 不是立即请求就能得到结果 在结果回调中返回
*/
requestPermissions(new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
} else {
//打开相机 前置摄像头
openCamera(front_camera);
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//设置相机自动对焦
mcamera.autoFocus(null);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//释放相机资源
if (mcamera != null) {
mcamera.release();
mcamera = null;
}
}
});
其中打开相机的方法
private void openCamera(int inDex) {
mcamera = Camera.open(inDex);
try {
mcamera.setPreviewDisplay(sf_camera.getHolder());//关联surfaceview,成为相机的预览界面
setCamra();
mcamera.startPreview();//开启预览
mcamera.autoFocus(null);
} catch (IOException e) {
e.printStackTrace();
}
}
3、设置屏幕的分辨率
不同机型的分辨率不同,我们这取最大分辨率进行相机预览
private void setCamra() {
Camera.Parameters parameters = mcamera.getParameters();
List<Camera.Size> sizeList = parameters.getSupportedPictureSizes();//得到手机支持的图片的尺寸的集合
int size = sizeList.size();
Camera.Size size1 = sizeList.get(0);
Log.d("qf", size1.height + "*" + size1.width + "=" + size1.width * size1.height);
Camera.Size size2 = sizeList.get(size - 1);
Log.d("qf", size2.height + "*" + size2.width + "=" + size2.width * size2.height);
//判断 去最大的尺寸为相机的分辨率
if (size1.height * size1.width > size2.width * size2.height) {
parameters.setPictureSize(size1.height, size1.width);
Log.d("qf", size1.height + "*" + size1.width + "=" + size1.width * size1.height);
} else {
parameters.setPictureSize(size2.height, size2.width);
Log.d("qf", size2.height + "*" + size2.width + "=" + size2.width * size2.height);
}
mcamera.setParameters(parameters);
mcamera.setDisplayOrientation(90);//预览结果屏幕飞正常显示 需要旋转屏幕
}
4、让相机点击屏幕可以进行聚焦,需要为SurfaceView设置触摸监听
sf_camera.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mcamera.autoFocus(null);
return true;
}
}
5、预览完成,可以进行拍照
调用相机的takePicture的方法进行拍照,拍照返回数据为一个byte数组,可转为bitmap并进行保存。
private void takePhotos() {
mcamera.takePicture(null, null, new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Bitmap btmap = rotateBitmap(bitmap);//旋转原bitmap得到新的bitmap
savePic(btmap);
bitmap.recycle();//回收原来的bitmap
mcamera.startPreview();
}
});
}
//对bitmap进行旋转
private Bitmap rotateBitmap(Bitmap bitmap) {
Matrix matrix = new Matrix();
matrix.reset();
if (isBack) {
matrix.postRotate(90);//后置摄像头需要进行90度旋转,前置进行-90度旋转
} else {
matrix.postRotate(-90);
}
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
}
6、进行图片保存
private void savePic(Bitmap bitmap) {
File filePath = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "CameraDemo");
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String name = format.format(new Date());
File file = new File(filePath.getPath() + File.separator + name + ".jpg");
BufferedOutputStream os;
try {
os = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);//进行图片压缩 保存在file路径下
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(Main2Activity.this, "拍照成功,图片存至" + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
}
7、设置一个boolean值记录目前相机是为前置或后置
boolean isBack = true;//true表示后置
8、得到系统相机的数量和相机信息,进行相机的切换
private void getCameraId() {
int numberOfCameras = Camera.getNumberOfCameras();
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
front_camera = i;
Log.d("print", front_camera + "前");
} else {
back_camera = i;
Log.d("print", back_camera + "后");
}
}
}
在相机切换时需要释放前一个相机
private void changeCamera() {
if (mcamera != null) {
mcamera.release();
mcamera = null;
}
if (isBack) {
openCamera(front_camera);
isBack = false;
} else {
openCamera(back_camera);
isBack = true;
}
}
这样就可以进行相机的拍照和摄像头的切换了。。