Camera2 API简介

Android 从5.0(21)开始,引入了新的Camera API Camera2,原来的android.hardware.Camera被废弃(下面称为Camera1),还有一个android.graphics.Camera,这个android.graphics.Camera不是用来照相的,是用来处理图像的,可以做出3D的图像效果之类的,之前的Camera1则由android.hardware.Camera代替。Camera2支持RAW输出,可以调节曝光,对焦模式,快门等,功能比原先Camera强大。

这里引用了管道的概念将安卓设备和摄像头之间联通起来,系统向摄像头发送 Capture 请求,而摄像头会返回 CameraMetadata。这一切建立在一个叫作 CameraCaptureSession 的会话中。

  • CameraManaer 摄像头管理器,用于检测摄像头,打开系统摄像头,调用CameraManager.getCameraCharacteristics(String)可以获取指定摄像头的相关特性
  • CameraCharacteristics 摄像头的特性
  • CameraDevice 摄像头,类似android.hardware.Camera也就是Camera1的Camera
  • CameraCaptureSession 这个类控制摄像头的预览或者拍照,setRepeatingRequest()开启预览,capture()拍照,CameraCaptureSession提供了StateCallback、CaptureCallback两个接口来监听CameraCaptureSession的创建和拍照过程。
  • CameraRequest和CameraRequest.Builder,预览或者拍照时,都需要一个CameraRequest对象。CameraRequest表示一次捕获请求,用来对照片的各种参数设置,比如对焦模式、曝光模式等。CameraRequest.Builder用来生成CameraRequest对象。

Camera2的简单使用(使用SurfaceView)

主要步骤:

  1. 获得摄像头管理器CameraManager mCameraManager,mCameraManager.openCamera()来打开摄像头
  2. 指定要打开的摄像头,并创建openCamera()所需要的CameraDevice.StateCallback stateCallback
  3. 在CameraDevice.StateCallback stateCallback中调用takePreview(),这个方法中,使用CaptureRequest.Builder创建预览需要的CameraRequest,并初始化了CameraCaptureSession,最后调用了setRepeatingRequest(previewRequest, null, childHandler)进行了预览
  4. 点击拍照按钮,调用takePicture(),这个方法内,最终调用了capture(mCaptureRequest, null, childHandler)
  5. 在new ImageReader.OnImageAvailableListener(){}回调方法中,将拍照拿到的图片进行展示

package org.hunter.a361camera.view;import android.Manifest;import android.content.Context;import android.content.pm.PackageManager;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.ImageFormat;import android.hardware.camera2.CameraAccessException;import android.hardware.camera2.CameraCaptureSession;import android.hardware.camera2.CameraCharacteristics;import android.hardware.camera2.CameraDevice;import android.hardware.camera2.CameraManager;import android.hardware.camera2.CaptureRequest;import android.media.Image;import android.media.ImageReader;import android.os.Build;import android.os.Bundle;import android.os.Handler;import android.os.HandlerThread;import android.support.annotation.Nullable;import android.support.annotation.RequiresApi;import android.support.v4.app.ActivityCompat;import android.support.v4.app.Fragment;import android.util.SparseIntArray;import android.view.LayoutInflater;import android.view.Surface;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.Toast;import org.hunter.a361camera.R;import java.nio.ByteBuffer;import java.util.Arrays;import static android.os.Looper.getMainLooper;/** * Main UI for the statistics screen. */public class CameraFragment extends Fragment {    public static final int REQUEST_CAMERA_CODE = 100;    public static final String PACKAGE = "package:";    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();    ///为了使照片竖直显示    static {        ORIENTATIONS.append(Surface.ROTATION_0, 90);        ORIENTATIONS.append(Surface.ROTATION_90, 0);        ORIENTATIONS.append(Surface.ROTATION_180, 270);        ORIENTATIONS.append(Surface.ROTATION_270, 180);    }    private SurfaceView mSurfaceView;    private SurfaceHolder mSurfaceHolder;    private ImageView iv_show;    private ImageView mCatture;    private CameraManager mCameraManager;//摄像头管理器    private Handler childHandler, mainHandler;    private String mCameraID;//摄像头Id 0 为后  1 为前    private ImageReader mImageReader;    private CameraCaptureSession mCameraCaptureSession;    private CameraDevice mCameraDevice;    /**     * 摄像头创建监听     */    private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {        @Override        public void onOpened(CameraDevice camera) {//打开摄像头            mCameraDevice = camera;            //开启预览            takePreview();        }        @Override        public void onDisconnected(CameraDevice camera) {//关闭摄像头            if (null != mCameraDevice) {                mCameraDevice.close();                CameraFragment.this.mCameraDevice = null;            }        }        @Override        public void onError(CameraDevice camera, int error) {//发生错误            Toast.makeText(getContext(), "摄像头开启失败", Toast.LENGTH_SHORT).show();        }    };    public static CameraFragment newInstance() {        return new CameraFragment();    }    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container,                             Bundle savedInstanceState) {        View root = inflater.inflate(R.layout.camera_frag, container, false);        initVIew(root);        initListener();        return root;    }    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);    }    @Override    public void onResume() {        super.onResume();    }    /**     * 初始化     */    private void initVIew(View root) {        iv_show = (ImageView) root.findViewById(R.id.iv_show_camera2);        //mSurfaceView        mSurfaceView = (SurfaceView) root.findViewById(R.id.surface_view_camera2);        mCatture = (ImageView) root.findViewById(R.id.capture);        mSurfaceHolder = mSurfaceView.getHolder();        mSurfaceHolder.setKeepScreenOn(true);        // mSurfaceView添加回调        mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {            @Override            public void surfaceCreated(SurfaceHolder holder) { //SurfaceView创建                // 初始化Camera                initCamera2();            }            @Override            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {            }            @Override            public void surfaceDestroyed(SurfaceHolder holder) { //SurfaceView销毁                // 释放Camera资源                if (null != mCameraDevice) {                    mCameraDevice.close();                    CameraFragment.this.mCameraDevice = null;                }            }        });    }    /**     * 初始化Camera2     */    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)    private void initCamera2() {        HandlerThread handlerThread = new HandlerThread("Camera2");        handlerThread.start();        childHandler = new Handler(handlerThread.getLooper());        mainHandler = new Handler(getMainLooper());        mCameraID = "" + CameraCharacteristics.LENS_FACING_FRONT;//后摄像头        mImageReader = ImageReader.newInstance(1080, 1920, ImageFormat.JPEG, 1);        mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { //可以在这里处理拍照得到的临时照片 例如,写入本地            @Override            public void onImageAvailable(ImageReader reader) {                //mCameraDevice.close();                // 拿到拍照照片数据                Image image = reader.acquireNextImage();                ByteBuffer buffer = image.getPlanes()[0].getBuffer();                byte[] bytes = new byte[buffer.remaining()];                buffer.get(bytes);//由缓冲区存入字节数组                final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);                if (bitmap != null) {                    iv_show.setImageBitmap(bitmap);                }            }        }, mainHandler);        //获取摄像头管理        mCameraManager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE);        try {            if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {                //申请WRITE_EXTERNAL_STORAGE权限                requestPermissions(new String[]{Manifest.permission.CAMERA},                        REQUEST_CAMERA_CODE);                //return;            } else {                //打开摄像头                mCameraManager.openCamera(mCameraID, stateCallback, mainHandler);            }        } catch (CameraAccessException e) {            e.printStackTrace();        }    }    @Override    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        if (requestCode == REQUEST_CAMERA_CODE) {            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {                // Permission Granted                try {                    mCameraManager.openCamera(mCameraID, stateCallback, mainHandler);                } catch (CameraAccessException e) {                    e.printStackTrace();                } catch (SecurityException e) {                    e.printStackTrace();                }            } else {                // Permission Denied            }        }    }    /**     * 开始预览     */    private void takePreview() {        try {            // 创建预览需要的CaptureRequest.Builder            final CaptureRequest.Builder previewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);            // 将SurfaceView的surface作为CaptureRequest.Builder的目标            previewRequestBuilder.addTarget(mSurfaceHolder.getSurface());            // 创建CameraCaptureSession,该对象负责管理处理预览请求和拍照请求            mCameraDevice.createCaptureSession(Arrays.asList(mSurfaceHolder.getSurface(), mImageReader.getSurface()), new CameraCaptureSession.StateCallback() // ③            {                @Override                public void onConfigured(CameraCaptureSession cameraCaptureSession) {                    if (null == mCameraDevice) return;                    // 当摄像头已经准备好时,开始显示预览                    mCameraCaptureSession = cameraCaptureSession;                    try {                        // 自动对焦                        previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);                        // 打开闪光灯                        previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);                        // 显示预览                        CaptureRequest previewRequest = previewRequestBuilder.build();                        mCameraCaptureSession.setRepeatingRequest(previewRequest, null, childHandler);                    } catch (CameraAccessException e) {                        e.printStackTrace();                    }                }                @Override                public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {                    Toast.makeText(getContext(), "配置失败", Toast.LENGTH_SHORT).show();                }            }, childHandler);        } catch (CameraAccessException e) {            e.printStackTrace();        }    }    /**     * 拍照     */    private void takePicture() {        if (mCameraDevice == null) return;        // 创建拍照需要的CaptureRequest.Builder        final CaptureRequest.Builder captureRequestBuilder;        try {            captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);            // 将imageReader的surface作为CaptureRequest.Builder的目标            captureRequestBuilder.addTarget(mImageReader.getSurface());            // 自动对焦            captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);            // 自动曝光            captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);            // 获取手机方向            int rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();            // 根据设备方向计算设置照片的方向            captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));            //拍照            CaptureRequest mCaptureRequest = captureRequestBuilder.build();            mCameraCaptureSession.capture(mCaptureRequest, null, childHandler);        } catch (CameraAccessException e) {            e.printStackTrace();        }    }    private void initListener() {        mCatture.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                takePicture();            }        });    }}

布局文件:

<?xml version="1.0" encoding="utf-8"?>            
源代码地址:https://github.com/gengqifu/361Camera。欢迎fork/star


更多相关文章

  1. RxMarkdown 是一个运用 RxJava API 在 TextView 或 EditText 中
  2. Android(安卓)Camera 使用小结
  3. Android前置摄像头预览并检测人脸,获取人脸区域亮度
  4. android Camera照相机技术(一)
  5. Android(安卓)相机实例
  6. Android(安卓)Camera应用初探一
  7. android Shape Drawable创建两边半圆的按钮背景【转】
  8. Android拍照得到的照片旋转了90度
  9. Android(安卓)Studio 插件

随机推荐

  1. 判断是否是第一次启动——Android模块化
  2. 手机震动效果
  3. Android定时闹钟与定时情景模式
  4. android将so打到jar包中并运行
  5. android 自定义ProgressBar 文字跟随进度
  6. 7 places to find help with developing
  7. android 单位测试
  8. Android(安卓)SDK Manager 无法更新SDK
  9. 解析 Android(安卓)开发时的 SDK 版本参
  10. Android设计模式之Abstract Factory