实现自定义相机(camera的使用)

实现自定义相机(camera的使用)

实现步骤

1.获取一个相机对象(Camera)
2.设置相机相关的回调和参数
3.创建一个预览界面(SurfaceView)、
4.捕捉一张图片(mCamera.takePicture(null, null, mPicture);)
5.保存图片
6.释放相机对象
虽然步骤很简单,但是设计到和硬件打交道就会设计到兼容性的问题,同事Android平台下碎片化严重,实现过程中还是会遇到很多坑。为了大家避免一些不必要的坑,我简单是现实了一个简单的demo。

具体代码如下

public class CameraActivity extends Activity {
    private static final int BUFFER_SIZE = 8 * 1024;
    private CameraPreview mPreview;
    private Button btn_take_picture;
    private Camera mCamera;
    private FrameLayout fl_camera_preview;
    private String imgOutputPath;
    private SurfaceHolder mHolder = null;
    private ImageView iv_flashLight;

    private View.OnClickListener mOnclickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_take_picture:
                    takePicture();
                    break;
                case R.id.iv_flashLight:
                    CameraUtils.toggleFlashLight(mCamera);
                    break;
            }

        }
    };

    private void takePicture() {
        if (null != mCamera) {
            mCamera.takePicture(null, null, mPicture);
        }
    }

    private Camera.PictureCallback mPicture = new Camera.PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            savePicture(data);
            setResult(RESULT_OK);
            CameraActivity.this.finish();
        }
    };

    private Camera.AutoFocusCallback mAutoFocusCallback = new Camera.AutoFocusCallback() {

        public void onAutoFocus(boolean success, Camera camera) {
            if (success) {
                KSLog2.KSLog().d("auto focus success!");
            } else {
                KSLog2.KSLog().d("auto focus failed!");
            }

        }
    };

    private CameraPreview.OnZoomListener zoomListener = new CameraPreview.OnZoomListener() {
        @Override
        public void onZoom(final float scaleFactor) {
            if (null == mCamera) return;
            mCamera.setParameters(CameraUtils.setZoom(mCamera.getParameters(), scaleFactor));
        }
    };

    private SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            // The Surface has been created, now tell the camera where to draw the preview.
            if (null == mCamera) return;
            try {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
//          mCamera.autoFocus(mAutoFocusCallback);
            } catch (IOException e) {
                e.printStackTrace();
                KSLog2.KSLog().d("Error setting camera preview: " + e.getMessage());
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            // empty. Take care of releasing the Camera preview in your activity.
            KSLog2.KSLog().d("surfaceDestroyed");
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
            // If your preview can change or rotate, take care of those events here.
            // Make sure to stop the preview before resizing or reformatting it.

            if (mHolder.getSurface() == null) {
                // preview surface does not exist
                return;
            }

            if (null == mCamera) return;

            // stop preview before making changes
            try {
                mCamera.stopPreview();
            } catch (Exception e) {
                e.printStackTrace();
                // ignore: tried to stop a non-existent preview
            }

            // set preview size and make any resize, rotate or
            // reformatting changes here

            // start preview with new settings
            try {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();


            } catch (Exception e) {
                KSLog2.KSLog().d("Error starting camera preview: " + e.getMessage());
            }
        }
    };

    private void savePicture(byte[] data) {
        if (TextUtils.isEmpty(imgOutputPath)) {
            KSLog2.KSLog().w("imgOutputPath is empty");
            return;
        }
        File pictureFile = new File(imgOutputPath);
        try {
            OutputStream os = new BufferedOutputStream(new FileOutputStream(pictureFile), BUFFER_SIZE);
            os.write(data);
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        parseIntentParams();
        PrepareView();

        KSLog2.KSLog().d("CameraActivity onCreate");
    }

    private void PrepareView() {
        btn_take_picture = (Button) findViewById(R.id.btn_take_picture);
        fl_camera_preview = (FrameLayout) findViewById(R.id.fl_camera_preview);
        iv_flashLight = (ImageView) findViewById(R.id.iv_flashLight);
        mPreview = new CameraPreview(this);
        mHolder = mPreview.getHolder();


        mHolder.addCallback(callback);
        btn_take_picture.setOnClickListener(mOnclickListener);
        iv_flashLight.setOnClickListener(mOnclickListener);
        mPreview.setOnZoomListener(zoomListener);
    }

    private void parseIntentParams() {
        Intent intent = getIntent();
        Uri uri = intent.getParcelableExtra(MediaStore.EXTRA_OUTPUT);
        if (uri == null) {
            throw new RuntimeException("EXTRA_OUTPUT is null");
        }
        KSLog2.KSLog().d("uri path = " + uri.getPath());
        imgOutputPath = uri.getPath();
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Create our Preview view and set it as the content of our activity.
        mCamera = CameraUtils.getCameraInstance(this);
        fl_camera_preview.addView(mPreview);
    }

    @Override
    protected void onPause() {
        super.onPause();
        releaseCamera(); // release the camera immediately on pause event
        fl_camera_preview.removeView(mPreview);
    }

    public  void releaseCamera() {
        if (mCamera != null) {
            mCamera.release(); // release the camera for other applications
            mCamera = null;
        }
    }

}

CameraUtils.java(相机工具类)

public class CameraUtils {
    public static final int PREVIEW_WIDTH = 720;
    public static final int PREVIEW_HEIGHT = 1280;

    public static final int PICTURE_WIDTH = 720;
    public static final int PICTURE_HEIGHT = 1280;


    private static void configCamera(Activity activity, Camera camera) {
        if (camera == null) return;
        // get Camera parameters
        Camera.Parameters params = camera.getParameters();
        //set preview size
        setPreviewWH(params);
        // set the focus mode
        setFocusMode(params);
        // set picture size
        setPictureSize(params);
        // set picture format
        params.setPictureFormat(ImageFormat.JPEG);
        // set Camera parameters
        camera.setParameters(params);
        camera.setDisplayOrientation(getCorrectOrientation(activity));
    }


    /**
     * A safe way to get an instance of the Camera object.
     */
    public static Camera getCameraInstance(Activity activity) {
        Camera camera = null;
        try {
            camera = Camera.open(); // attempt to get a Camera instance
            configCamera(activity, camera);
        } catch (Exception e) {
            e.printStackTrace();
            // Camera is not available (in use or does not exist)
        }
        return camera; // returns null if camera is unavailable
    }





    /**
     * Check if this device has a camera
     */
    public static boolean checkCameraHardware(Context context) {
        if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
            // this device has a camera
            return true;
        } else {
            // no camera on this device
            return false;
        }
    }


    private static void setPreviewWH(Camera.Parameters params) {
        List<Camera.Size> previewsSizes = params.getSupportedPreviewSizes();
        Collections.sort(previewsSizes, new Comparator<Camera.Size>() {
            @Override
            public int compare(Camera.Size lhs, Camera.Size rhs) {
                if ((lhs.width * lhs.height) > (rhs.width * rhs.height)) {
                    return 1;
                } else {
                    return -1;
                }
            }
        });
        for (Camera.Size size : previewsSizes) {
            if (size.width >= PREVIEW_WIDTH && size.height >= PREVIEW_HEIGHT) {
                params.setPreviewSize(size.width, size.height);
                KSLog2.KSLog().d("preview width = " + size.width + " preview height = " + size.height);
                return;
            }
        }
    }


    private static void setFocusMode(Camera.Parameters params) {
        List<String> focusModes = params.getSupportedFocusModes();
        if (focusModes != null) {
            if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            } else if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            } else if (focusModes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
                params.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
            }
        }
    }


    private static void setPictureSize(Camera.Parameters params) {
        List<Camera.Size> PictureSize = params.getSupportedPictureSizes();
        Collections.sort(PictureSize, new Comparator<Camera.Size>() {
            @Override
            public int compare(Camera.Size lhs, Camera.Size rhs) {
                if ((lhs.width * lhs.height) > (rhs.width * rhs.height)) {
                    return -1;
                } else {
                    return 1;
                }
            }
        });
        for (Camera.Size size : PictureSize) {
            if (size.width >= PICTURE_WIDTH && size.height >= PICTURE_HEIGHT) {
                params.setPictureSize(size.width, size.height);
                KSLog2.KSLog().d("picture width = " + size.width + " picture height = " + size.height);
                return;
            }
        }
    }


    public static Camera.Parameters setZoom(Camera.Parameters params, float scaleFactor) {
        if (!params.isZoomSupported()) return params;
        try {
            int addValue = (int) ((scaleFactor - 1.0f) * params.getMaxZoom());
            int value = params.getZoom() + addValue;
            if (value > params.getMaxZoom()) {
                value = params.getMaxZoom();
            }
            if (value < 0) {
                value = 0;
            }
            KSLog2.KSLog().d("zoom value = " + value + "scaleFactor = " + scaleFactor);
            params.setZoom(value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return params;
    }


    public static boolean toggleFlashLight(Camera camera) {
        if (null == camera) return false;
        try {
            Camera.Parameters parameters = camera.getParameters();
            List<String> flashModes = parameters.getSupportedFlashModes();
            String flashMode = parameters.getFlashMode();
            if (!Camera.Parameters.FLASH_MODE_TORCH.equals(flashMode)) {
                if (flashModes.contains(Camera.Parameters.FLASH_MODE_TORCH)) {
                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                    camera.setParameters(parameters);
                    return true;
                }
            } else if (!Camera.Parameters.FLASH_MODE_OFF.equals(flashMode)) {
                if (flashModes.contains(Camera.Parameters.FLASH_MODE_OFF)) {
                    parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                    camera.setParameters(parameters);
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            KSLog2.KSLog().d("toggleFlashLight,failed" + e.getMessage());
            return false;
        }
        return false;
    }


    private static int getCorrectOrientation(Activity activity) {
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(findFacingBackCameraID(), info);
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0: degrees = 0; break;
            case Surface.ROTATION_90: degrees = 90; break;
            case Surface.ROTATION_180: degrees = 180; break;
            case Surface.ROTATION_270: degrees = 270; break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        // 记录本机子相机的旋转角度
        return result;
    }


    private static int findFacingBackCameraID() {
        int cameraId = -1;
        // Search for the back facing camera
        int numberOfCameras = Camera.getNumberOfCameras();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(i, info);
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                KSLog2.KSLog().d("Camera found");
                cameraId = i;
                break;
            }
        }
        return cameraId;
    }


}

CameraPreview.java(负责显示相机预览图片)

public class CameraPreview extends SurfaceView {
    private final ScaleGestureDetector scaleGestureDetector;
    private CameraPreview.OnZoomListener mListener;

    public interface OnZoomListener {
        public void onZoom(float scaleFactor);
    }

    private ScaleGestureDetector.OnScaleGestureListener onScaleGestureListener = new ScaleGestureDetector.OnScaleGestureListener() {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            float scaleFactor = detector.getScaleFactor();
            if(null != mListener) {
                mListener.onZoom(scaleFactor);
            }
            return true;
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {

        }
    };


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        KSLog2.KSLog().d(" onTouchEvent");
        if (scaleGestureDetector.onTouchEvent(event)) {
            return true;
        }
        return super.onTouchEvent(event);
    }


    public CameraPreview(Context context) {
        super(context);
        scaleGestureDetector = new ScaleGestureDetector(context, onScaleGestureListener);
    }

    public void setOnZoomListener(OnZoomListener mListener) {
        this.mListener = mListener;
    }
}

布局代码

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <Button
        android:id="@+id/btn_take_picture"
        android:text="Capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center"/>



    <FrameLayout
        android:layout_above="@+id/btn_take_picture"
        android:id="@+id/fl_camera_preview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>


    <ImageView
        android:id="@+id/iv_flashLight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:src="@drawable/public_icon"/>

</RelativeLayout>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值