Android 自定义Camera全屏拍照,支持前后摄像头

最近项目中一直在调用系统相机拍照,而产品总是要求拍照页面向iOS看齐,真是很头疼啊。但问题还是存在,有必要搞一个自定义的啦。在网上搜索了一段时间后,发现还真不是那么好实现的,实践之后,总结一些要点如下:

1.camera的parameters设置总是会提示出setParamters failed的异常

2.预览和图片的尺寸设置

3.预览图片变形

4.自动聚焦

5.保存的图片旋转角度

以上是我遇到的难点,并将之一一解决后的总结。


第1个问题,setPreviewFrameRate和setPreviewSize不能放在一起使用,否则set的时候必然报错,这个也是在查看了源代码后发现的。

第2个问题,每个手机都有自己支持的尺寸集合,并不是设置一个固定的宽高就可以的,所以要想设置尺寸,一定是先获取手机支持的尺寸,而且排序也不一样,有的从大到小,有的从小到大。没办法,开源嘛。

第3个问题就是surfaceview的尺寸大小,设置的不对的话,会导致预览变形,这个要和预览尺寸配合着设置

第4个问题比较容易解决一点,网上有很多种设置方式,但是最好用的就是使用重力加速度类型的传感器来实现,这个效果是最好的,在配合上触屏操作时也加上自动聚焦功能,就能保证自动聚焦这个功能完美的实现了。

第5个问题就是拍照会转动手机在各种角度拍照,那么获取的图片显示的时候有要求的需要根据角度重新生成bitmap,然后再显示啦。这个使用Matrix类就能实现,但是难点在于如何获取到正确的旋转角度。通常都会使用getWindowManager().getDefaultDisplay().getRotation();这个方法,但是当我将这个相机Activity设置成portrait时,这个方法是无效的,因此必须使用OrientationEventListener这个监听器,其实这个也是利用传感器实现的方向监听。


好了,以上总是我遇到的一些问题,以及一些总结,下面直接贴出代码,就不上传工程啦。所有的代码都写在一个activity里面了,还没有做架构抽象,感兴趣的小伙伴可以抽象一下,反馈给我,呵呵。


CameraManager.java

import android.content.Context;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.view.SurfaceHolder;
import android.widget.Toast;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Created by zouguibao on 2017/11/23.
 */

public class CameraManger {
    private static CameraManger instance;
    private Camera camera;
    private MediaPlayer mShootSound;

    public static final int TYPE_PREVIEW = 0;
    public static final int TYPE_PICTURE = 1;
    public static final int ALLOW_PIC_LEN = 2000;       //最大允许的照片尺寸的长度   宽或者高

    private int cameraPosition;

    private CameraManger() {

    }

    public static CameraManger getInstance() {
        if (instance == null) {
            instance = new CameraManger();
        }
        return instance;
    }

    /**
     * 打开摄像头
     *
     * @param holder
     * @param autoFocusCallback
     * @param degree
     */
    public void openCamera(SurfaceHolder holder, Camera.AutoFocusCallback autoFocusCallback, int degree) {
        try {
            //初始化摄像头
            cameraPosition = Camera.CameraInfo.CAMERA_FACING_BACK;
            // 打开摄像头
            camera = Camera.open(cameraPosition);
            // 设置用于显示拍照影像的SurfaceHolder对象
            camera.setPreviewDisplay(holder);
            camera.setDisplayOrientation(degree);
            camera.autoFocus(autoFocusCallback);

        } catch (Exception e) {
//                e.printStackTrace();
            camera.release();
            camera = null;
        }
    }

    /**
     * 设置参数
     */
    public void setCameraParameters(int screenWidth, int screenHeight) {
        try {
            if (camera != null) {
                Camera.Parameters parameters = camera.getParameters();//获取各项参数
                Camera.Size previewSize = findFitPreResolution(parameters);
                parameters.setPreviewSize(previewSize.width, previewSize.height);// 设置预览大小

                parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                parameters.setPictureFormat(PixelFormat.JPEG);//设置图片格式
                //不能与setPreviewSize一起使用,否则setParamters会报错
//                    parameters.setPreviewFrameRate(5);//设置每秒显示4帧
                parameters.setJpegQuality(80);// 设置照片质量
                Camera.Size pictureSize = null;
                if (equalRate(screenWidth, screenHeight, 1.33f)) {
                    pictureSize = findFitPicResolution(parameters, (float) 4 / 3);
                } else {
                    pictureSize = findFitPicResolution(parameters, (float) 16 / 9);
                }

                parameters.setPictureSize(pictureSize.width, pictureSize.height);// 设置保存的图片尺寸
                camera.setParameters(parameters);
                camera.startPreview();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private boolean equalRate(int width, int height, float rate) {
        float r = (float) width / (float) height;
        if (Math.abs(r - rate) <= 0.2) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 摄像头切换
     *
     * @param holder
     * @param autoFocusCallback
     * @param degree
     */
    public void turnCamera(SurfaceHolder holder, Camera.AutoFocusCallback autoFocusCallback, int degree, int screenWidth, int screenHeight) {
        //切换前后摄像头
        //现在是后置,变更为前置
        if (camera != null && cameraPosition == Camera.CameraInfo.CAMERA_FACING_BACK) {
            camera.stopPreview();//停掉原来摄像头的预览
            camera.release();//释放资源
            camera = null;//取消原来摄像头
            camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);//打开当前选中的摄像头
            try {
                camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面
                camera.setDisplayOrientation(degree);
                camera.autoFocus(autoFocusCallback);
                setCameraParameters(screenWidth, screenHeight);
            } catch (IOException e) {
                e.printStackTrace();
            }
            camera.startPreview();//开始预览
            cameraPosition = Camera.CameraInfo.CAMERA_FACING_FRONT;
            DataUtils.isBackCamera = false;
        } else if (cameraPosition == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            //代表摄像头的方位,CAMERA_FACING_FRONT前置
            // CAMERA_FACING_BACK后置
            //现在是前置, 变更为后置
            camera.stopPreview();//停掉原来摄像头的预览
            camera.release();//释放资源
            camera = null;//取消原来摄像头
            camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);//打开当前选中的摄像头
            try {
                camera.setPreviewDisplay(holder);//通过surfaceview显示取景画面
                camera.setDisplayOrientation(degree);
                camera.autoFocus(autoFocusCallback);
                setCameraParameters(screenWidth, screenHeight);
            } catch (IOException e) {
                e.printStackTrace();
            }
            camera.startPreview();//开始预览
            cameraPosition = Camera.CameraInfo.CAMERA_FACING_BACK;
            DataUtils.isBackCamera = true;
        }
    }

    public void setCameraZoom(int scale) {
        Camera.Parameters parameters = camera.getParameters();
        int zoom = parameters.getZoom() + scale;
        if (zoom < 0) zoom = 0;
        if (zoom > parameters.getMaxZoom())
            zoom = parameters.getMaxZoom();
        parameters.setZoom(zoom);
        camera.setParameters(parameters);
    }

    public boolean setCameraFocusAreas(Point point) {
        if (camera == null) {
            return false;
        }

        Camera.Parameters parameters = null;
        try {
            parameters = camera.getParameters();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        //不支持设置自定义聚焦,则使用自动聚焦,返回
        if (parameters.getMaxNumFocusAreas() <= 0) {
            return false;
        }
        List areas = new ArrayList();

        int left = point.x - 300;
        int top = point.y - 300;
        int right = point.x + 300;
        int bottom = point.y + 300;

        left = left < -1000 ? -1000 : left;
        top = top < -1000 ? -1000 : top;
        right = right > 1000 ? 1000 : right;
        bottom = bottom > 1000 ? 1000 : bottom;

        areas.add(new Camera.Area(

你可能感兴趣的:(android,android,图片,传感器)