Android surfaceview 自定义相机 拍照(闪光灯、前后摄像头)

时间:2022-09-18 06:03:55

在我们app中经常会调用相机进行拍照,然后把拍下来的图片保存在本地,再上传到服务端,网上有不少自定义的相机,也下载了不少,但是效果还是不满意,所以决定自定义下,不多说了,直接上代码:

public class CameraViews extends SurfaceView implements SurfaceHolder.Callback{ 
private String TAG=Camera.class.getName();
private Activity mActivity=null;
private Camera camera=null;
private SurfaceHolder holder=null;
/* 是否打开前置相机,true为前置,false为后置 */
private boolean mIsFrontCamera=false;
/是否开启闪光灯 默认关闭闪光灯/
private String isOpenFlashMode= Camera.Parameters.FLASH_MODE_OFF;
private int curRotation=0;
private CameraCallback mCallback=null;

public CameraViews(Context context){
super(context);
initSurface();
}

public CameraViews(Context context, AttributeSet attrs) {
super(context, attrs);
initSurface();
}

public void setCurActivity(Activity activity){
this.mActivity=activity;
}

/**
* @Description: 初始化surface
*/
private void initSurface(){
holder =getHolder();//获得句柄
holder.addCallback(this);//添加回调
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//surfaceview不维护自己的缓冲区,等待屏幕渲染引擎将内容推送到用户面前
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if(camera==null){
openCamera();
}
initCameraParams(mActivity);
camera.setPreviewDisplay(getHolder());
camera.startPreview();
} catch (Exception e) {
Toast.makeText(getContext(), "打开相机失败", Toast.LENGTH_SHORT).show();
Log.e(TAG,e.getMessage());
}
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
//try{
//camera.stopPreview();
//摄像头画面显示在Surface上
//camera.setPreviewDisplay(holder);
//initCameraParams(mActivity);
//camera.startPreview();
//}catch(IOException e) {
// if (camera != null) camera.release();
//camera = null;
//}

//注意:这里不能进行重新初始化相机,然后在预览,不然进行横纵拍照,照出来的图片旋转的角度会对应不上,所以这里直接开启预览就好
camera.startPreview();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera=null;
holder=null;

}

@SuppressWarnings("unused")
private PictureCallback pictureCallback=new PictureCallback() {

@Override
public void onPictureTaken(byte[] data, Camera camera) {
saveCameraImage(data, camera);
//这句话也很重要,是将你拍照成功后,图片可以在相册中查看到。(只不过我把这句话封装到保存图片中,保存图片顺带加载到相册)。
//MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");
//重新打开预览图,进行下一次的拍照准备
camera.startPreview();
}
};
/**
* @Description:设置相机预览
* @param activity
**/
public void setCameraPreView(){
if(camera!=null){
camera.stopPreview();
initCameraParams(mActivity);
try {
camera.setPreviewDisplay(getHolder());
camera.startPreview();
} catch (IOException e) {
Log.e(">>>>>","相机转换失败!"+e.getMessage());
}
}else{
Log.e(">>>>>","相机初始化失败!");
}
}

/**
* @Description:保存拍照的图片
* @Since:2015-8-11
* @Version:1.1.0
* @param data
* @param camera
*/
private void saveCameraImage(byte[] data, Camera camera) {
if(data==null){
Log.e(TAG, "获取图片流失败,拍照失败,请重试!");
return;
}
if(isFrontCamera()){
if(curRotation==90){
curRotation=270;
}else if(curRotation==270){
curRotation=90;
}
}
Bitmap thumbBM=null;
thumbBM=BitmapUtils.getInstance().save(mActivity,data,curRotation);
mCallback.onCameraCallback(thumbBM);
thumbBM=null;

}

/**
* @Description:设置相机参数
*/
public void initCameraParams(Activity activity){
Camera.Parameters parameters = camera.getParameters();
// 选择合适的预览尺寸
List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();
if (sizeList.size()>0) {
Size cameraSize=sizeList.get(0);
//预览图片大小
parameters.setPreviewSize(cameraSize.width, cameraSize.height);
}

//设置生成的图片大小
sizeList = parameters.getSupportedPictureSizes();
if (sizeList.size()>0) {
Size cameraSize=sizeList.get(0);
for (Size size : sizeList) {
//小于100W像素
if (size.width*size.height<100*10000) {
cameraSize=size;
break;
}
}
parameters.setPictureSize(cameraSize.width, cameraSize.height);
}
//设置图片格式
parameters.setPictureFormat(ImageFormat.JPEG);
parameters.setJpegQuality(100);
parameters.setJpegThumbnailQuality(100);
//自动聚焦模式
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
parameters.setFlashMode(getIsOpenFlashMode());
//curRotation=getPreviewDegree();
screenDirectionListener();
//Log.e(">>>>>","curRotation:"+curRotation);
//parameters.setRotation(curRotation);//生成的图片转90°
//camera.setDisplayOrientation(curRotation);//预览转90°预览图片旋转90°
//camera.setDisplayOrientation(getPreviewDegree());//预览旋转90°
camera.setDisplayOrientation(90);
camera.setParameters(parameters);
}
public String getIsOpenFlashMode() {
return isOpenFlashMode;
}

/**
* @Description: 设置开启闪光灯(重新预览)
* @param mIsOpenFlashMode
*/
public void setIsOpenFlashMode(boolean mIsOpenFlashMode) {
if(mIsOpenFlashMode)
this.isOpenFlashMode = Camera.Parameters.FLASH_MODE_ON;
else
this.isOpenFlashMode = Camera.Parameters.FLASH_MODE_OFF;;
setCameraPreView();//重新预览相机
}

/**
* 根据当前照相机状态(前置或后置),打开对应相机
*/
private boolean openCamera() {
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
}

if(mIsFrontCamera){
Camera.CameraInfo cameraInfo=new CameraInfo();
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
Camera.getCameraInfo(i, cameraInfo);
if(cameraInfo.facing==Camera.CameraInfo.CAMERA_FACING_FRONT){
try {
camera=Camera.open(i);
} catch (Exception e) {
camera =null;
return false;
}
}
}
}else {
try {
camera=Camera.open();
} catch (Exception e) {
camera =null;
return false;
}
}
return true;
}

/**
* @Description:获取相机摄像头个数
* @return
*/
public int getCameraCount(){
return Camera.getNumberOfCameras();//得到摄像头的个数
}

private boolean isFrontCamera(){
return mIsFrontCamera;
}

/**
* @Description:转换前置和后置照相机
* @return
*/
public boolean switchCamera(){
mIsFrontCamera=!mIsFrontCamera;
openCamera();
if(camera!=null){
initCameraParams(mActivity);
//updateCameraOrientation();
try {
camera.setPreviewDisplay(getHolder());
camera.startPreview();
} catch (IOException e) {
Log.e(">>>>>","相机转换失败!"+e.getMessage());
}
}
return mIsFrontCamera;
}

/**
* @Description: 拍照

* @param mCameraCallback
*/
public void takePhoto(CameraCallback mCameraCallback){
try {
initSurface();
initCameraParams(mActivity);
camera.takePicture(null, null, pictureCallback);//将拍摄到的照片给自定义的对象
this.mCallback=mCameraCallback;
} catch (Exception e) {
Toast.makeText(mActivity,"初始化相机失败!",Toast.LENGTH_SHORT).show();
}
}
public interface CameraCallback{
void onCameraCallback(Bitmap bitmap);
}
/**
* @Description: 监听屏幕的旋转方向
*/
private void screenDirectionListener(){
OrientationEventListener mOrEventListener =new OrientationEventListener(getContext()) {

@Override
public void onOrientationChanged(int rotation) {
//getScreenDirect();
if (((rotation >= 0) && (rotation <= 45)) || (rotation >= 315)||((rotation>=135)&&(rotation<=225))){////portrait
} else if (((rotation > 45) && (rotation < 135))||((rotation>225)&&(rotation<315))) {//landscape
}
if (((rotation >= 0) && (rotation <= 45)) || (rotation > 315)){//纵屏向上
rotation=90;
}else if ((rotation > 45) && (rotation <= 135)) {//横屏向右
rotation=180;
}
else if ((rotation > 135) && (rotation <= 225)) {//纵屏向下
rotation=270;
}
else if((rotation > 225) && (rotation <= 315)) { //横屏向左
rotation=0;
}else {
rotation=0;
}
curRotation=rotation;
}
};
mOrEventListener.enable();
}