码迷,mamicode.com
首页 > 移动开发 > 详细

Android CameraManager 类

时间:2017-10-17 12:16:02      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:nal   logs   字节   select   off   gets   pre   gif   info   

先看代码:

    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    private CameraManager cameraManager;

        cameraManager = new CameraManager(this);
        mSurfaceView = (SurfaceView) findViewById(R.id.java_surface_view);
        mSurfaceHolder = mSurfaceView.getHolder();

        // mSurfaceView 不需要自己的缓冲区
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        // mSurfaceView添加回调
        mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) { //SurfaceView创建
                try {
                    cameraManager.openDriver(mSurfaceHolder);
                    cameraManager.startPreview();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) { //SurfaceView销毁
                holder.removeCallback(this); // Camera is being used after Camera.release() was called
                cameraManager.stopPreview();
                cameraManager.closeDriver();

            }
        });

自定义一个 CameraManager 类,在关闭当前页面,释放camera资源时偶尔报错 

Camera is being used after Camera.release() was called

第一次,加了一句 holder.removeCallback(this); 运行发现还是时不时出现报错。

第二次在释放 camera前加  camera.setPreviewCallback(null); 问题解决。

    /**
     * 关闭预览
     */
    public synchronized void stopPreview() {
        Log.e(TAG, "stopPreview");
        if (autoFocusManager != null) {
            autoFocusManager.stop();
            autoFocusManager = null;
        }
        if (camera != null && previewing) {
            camera.stopPreview();
            camera.setPreviewCallback(null);  // Camera is being used after Camera.release() was called
            previewing = false;
        }
    }



    /**
     * 关闭camera
     */
    public synchronized void closeDriver() {
        Log.e(TAG, "closeDriver");
        if (camera != null) {
            camera.release();
            camera = null;
        }
    }

原来:如果程序中加入了previewCallback,在surfaceDestroy释放camera的时候,最好执行myCamera.setOneShotPreviewCallback(null); 或者myCamera.setPreviewCallback(null);中止这种回调,然后再释放camera更安全。否则可能会报错。 

 

 

附:CameraManager类:

 

技术分享
package com.lemoncome.facedetection;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.WindowManager;

import java.io.IOException;
import java.util.List;

/**
 * User:lizhangqu(513163535@qq.com)
 * Date:2015-09-05
 * Time: 10:56
 */
public class CameraManager implements Camera.PreviewCallback {
    private static final String TAG = CameraManager.class.getName();
    private Camera camera;
    private Camera.Parameters parameters;
    private AutoFocusManager autoFocusManager;
    private int requestedCameraId = -1;
    private Context mContext;

    private boolean initialized;
    private boolean previewing;

    /**
     * 打开摄像头
     *
     * @param cameraId 摄像头id
     * @return Camera
     */
    public Camera open(int cameraId) {
        int numCameras = Camera.getNumberOfCameras();
        if (numCameras == 0) {
            Log.e(TAG, "No cameras!");
            return null;
        }
        boolean explicitRequest = cameraId >= 0;
        if (!explicitRequest) {
            // Select a camera if no explicit camera requested
            int index = 0;
            while (index < numCameras) {
                Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
                Camera.getCameraInfo(index, cameraInfo);
                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                    break;
                }
                index++;
            }
            cameraId = index;
        }
        Camera camera;
        if (cameraId < numCameras) {
            Log.e(TAG, "Opening camera #" + cameraId);
            camera = Camera.open(cameraId);
        } else {
            if (explicitRequest) {
                Log.e(TAG, "Requested camera does not exist: " + cameraId);
                camera = null;
            } else {
                Log.e(TAG, "No camera facing back; returning camera #0");
                camera = Camera.open(0);
            }
        }
        int rotation = getDisplayOrientation();
        camera.setDisplayOrientation(rotation);
        camera.setPreviewCallback(this);
        return camera;
    }

    public int getDisplayOrientation() {
        Display display = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        int rotation = display.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;
        }

        Camera.CameraInfo camInfo =
                new Camera.CameraInfo();
        Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, camInfo);

        int result = (camInfo.orientation - degrees + 360) % 360;
        return result;
    }

    public CameraManager(Context context) {
        mContext = context;
    }


    /**
     * 打开camera
     *
     * @param holder SurfaceHolder
     * @throws IOException IOException
     */
    public synchronized void openDriver(SurfaceHolder holder)
            throws IOException {
        Log.e(TAG, "openDriver");
        Camera theCamera = camera;
        if (theCamera == null) {
            theCamera = open(requestedCameraId);
            if (theCamera == null) {
                throw new IOException();
            }
            camera = theCamera;
        }
        theCamera.setPreviewDisplay(holder);

        if (!initialized) {
            initialized = true;
            parameters = camera.getParameters();
            List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes();

            int w = 800;
            int h = 600;
            for (Camera.Size size : previewSizes) {
                Log.e("TAG", "previewSizes width:" + size.width);
                Log.e("TAG", "previewSizes height:" + size.height);
                if (size.width - w <= 100 & size.width >= w) {
                    w = size.width;
                    h = size.height;
                    break;
                }
            }

            parameters.setPreviewSize(w, h);
            parameters.setPictureFormat(ImageFormat.JPEG);
            parameters.setJpegQuality(100);
            parameters.setPictureSize(800, 600);
            theCamera.setParameters(parameters);
        }
    }

    /**
     * camera是否打开
     *
     * @return camera是否打开
     */
    public synchronized boolean isOpen() {
        return camera != null;
    }

    /**
     * 关闭camera
     */
    public synchronized void closeDriver() {
        Log.e(TAG, "closeDriver");
        if (camera != null) {
            camera.release();
            camera = null;
        }
    }

    /**
     * 开始预览
     */
    public synchronized void startPreview() {
        Log.e(TAG, "startPreview");
        Camera theCamera = camera;
        if (theCamera != null && !previewing) {
            theCamera.startPreview();
            previewing = true;
            autoFocusManager = new AutoFocusManager(camera);
        }
    }

    /**
     * 关闭预览
     */
    public synchronized void stopPreview() {
        Log.e(TAG, "stopPreview");
        if (autoFocusManager != null) {
            autoFocusManager.stop();
            autoFocusManager = null;
        }
        if (camera != null && previewing) {
            camera.stopPreview();
            camera.setPreviewCallback(null);  // Camera is being used after Camera.release() was called
            previewing = false;
        }
    }

    public void setPreviewCallback(Camera.PreviewCallback cb) {
        camera.setOneShotPreviewCallback(this);
    }

    /**
     * 打开闪光灯
     */
    public synchronized void openLight() {
        Log.e(TAG, "openLight");
        if (camera != null) {
            parameters = camera.getParameters();
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
            camera.setParameters(parameters);
        }
    }

    /**
     * 关闭闪光灯
     */
    public synchronized void offLight() {
        Log.e(TAG, "offLight");
        if (camera != null) {
            parameters = camera.getParameters();
            parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            camera.setParameters(parameters);
        }
    }

    /**
     * 拍照
     *
     * @param shutter ShutterCallback
     * @param raw     PictureCallback
     * @param jpeg    PictureCallback
     */
    public synchronized void takePicture(final Camera.ShutterCallback shutter, final Camera.PictureCallback raw,
                                         final Camera.PictureCallback jpeg) {
        camera.takePicture(shutter, raw, jpeg);
    }

    @Override
    public void onPreviewFrame(byte[] bytes, Camera camera) {

    }

    private Bitmap reSize(byte[] data) {
        Log.i(TAG, "myJpegCallback:onPictureTaken...");
        Bitmap cutMap = BitmapFactory.decodeByteArray(data, 0, data.length);//data是字节数据,将其解析成位图
        //设置FOCUS_MODE_CONTINUOUS_VIDEO)之后,myParam.set("rotation", 90)失效。图片竟然不能旋转了,故这里要旋转下
        Matrix matrix = new Matrix();
        matrix.postRotate((float) 90.0);
        Bitmap rotaBitmap = Bitmap.createBitmap(cutMap, 0, 0, cutMap.getWidth(), cutMap.getHeight(), matrix, false);

        //旋转后rotaBitmap是960×1280.预览surfaview的大小是540×800
        //将960×1280缩放到540×800
        Bitmap sizeBitmap = Bitmap.createScaledBitmap(rotaBitmap, 540, 800, true);
        Bitmap rectBitmap = Bitmap.createBitmap(sizeBitmap, 100, 200, 300, 300);//截取
        return rectBitmap;
    }
}
CameraManager

 

Android CameraManager 类

标签:nal   logs   字节   select   off   gets   pre   gif   info   

原文地址:http://www.cnblogs.com/haoxr/p/7680140.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!