Android -- Camera2(Android5.0)

Camera2

Camera2是Android5.0中的其中一个新的特性,新的API。与原来的camera API相比,不同之处在于:

  • 原生支持RAW照片输出
  • 突发拍摄模式

制约拍照速度的不再是软件而是硬件。以Nexus 5为例,分辨率全开下Andorid L的连拍速度可达到30fps。

  • 全手动控制

快门、感光度、对焦、测光、硬件视频防抖等多种参数都被整合到了新的API内。新的API中添加的手动控制功能列表:

  1. 感光度
  2. 手动对焦/AF开关
  3. AE/AF/AWB模式
  4. AE/AWB锁
  5. 硬件视频防抖
  6. 连续帧

干货

Camera2 程序逻辑与原Camera有很大不同。

CameraManager,系统服务,通过 CameraManager去获得camera设备对象。CameraDevices提供描述相机硬件设备支持可用的和输出的参数,这些信息通过 CameraCharacteristics获得,CameraCharacteristics又是从 getCameraCharacteristics(cameraId)获得,通过freamwork中的源码发现,其实这里就是直接调用的Camera API接口。

通过camera拍照,应用首先要创建由相机设备的输出surface组成的拍照会话,createCaptureSession(List, CameraCaptureSession.StateCallback, Handler)。每个surface必须预先设置适当的大小和格式去匹配相机设备的可支持的大小和格式。一个目标surface可以从不同的类中获取,包括SurfaceView,SurfaceTexture via Surface(SurfaceTexture), MediaCodec, MediaRecorder, Allocation, and ImageReader.

一旦请求被建立,他可以交给活动的拍照会话:一次拍照(one-shot )或者无止境连续拍照或预览(Repeating)。两种方法都有一个其他的方式:接受一系列的请求作为burst拍照/重复burst。

public void openCamera (String cameraId, CameraDevice.StateCallback callback, Handler handler)

使用getCameraIdList()来获得可用摄像设备的列表。一旦成功打开相机,CameraDevice.StateCallback中的onOpened(CameraDevice)将被调用。相机设备可以通过调用createCaptureSession()和createCaptureRequest()去设置操作。如果打开相机设备失败,那么设备回调的onError方法将被调用,和后续调用相机设备将抛出一个CameraAccessException。

public abstract CaptureRequest.Builder createCaptureRequest (int templateType)

为请求拍照创建一个CaptureRequest.Builder,初始化目标用例的模板。选择最好的设置为特定的相机设备,所以不建议为不同的相机设备重用相同的请求,创建一个builder为具体的设备和模板和根据需要覆盖的设置。

public abstract void createCaptureSession (List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)

活动着的会话决定了相机的output Surfaces 为每个拍照的要求。给定请求可以使用全部或只有部分的output Surfaces。一旦CameraCaptureSession创建,可以提交capture请求、captureBurst请求,setRepeatingRequest请求或setRepeatingBurst请求。

权限

<uses-permission android:name="android.permission.CAMERA"/>

布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <TextureView
        android:id="@+id/textureview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

</LinearLayout>

核心代码

public class CameraFragment extends Fragment implements TextureView.SurfaceTextureListener {

    private TextureView mPreviewView;
    private Handler mHandler;
    private HandlerThread mThreadHandler;
    private Size mPreviewSize;
    private CaptureRequest.Builder mPreviewBuilder;

    public static CameraFragment newInstance() {
        return new CameraFragment();
    }

    @SuppressWarnings("ResourceType")
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.camera_frag, null);
        initLooper();
        initUIAndListener(v);
        return v;
    }
    //很多过程都变成了异步的了,所以这里需要一个子线程的looper
    private void initLooper() {
        mThreadHandler = new HandlerThread("CAMERA2");
        mThreadHandler.start();
        mHandler = new Handler(mThreadHandler.getLooper());
    }
    //可以通过TextureView或者SurfaceView
    private void initUIAndListener(View v) {
        mPreviewView = (TextureView) v.findViewById(R.id.textureview);
        mPreviewView.setSurfaceTextureListener(this);
    }

    @SuppressWarnings("ResourceType")
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        try {
            //获得CameraManager
            CameraManager cameraManager = (CameraManager) getActivity().getSystemService(Context.CAMERA_SERVICE);
            //获得属性
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics("0");
            //支持的STREAM CONFIGURATION
            StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
            //显示的size
            mPreviewSize = map.getOutputSizes(SurfaceTexture.class)[0];
            //打开相机
            cameraManager.openCamera("0", mCameraDeviceStateCallback, mHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return false;
    }

    //TextureView.SurfaceTextureListener
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    private CameraDevice.StateCallback mCameraDeviceStateCallback = new CameraDevice.StateCallback() {

        @Override
        public void onOpened(CameraDevice camera) {
            try {
                startPreview(camera);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onDisconnected(CameraDevice camera) {

        }

        @Override
        public void onError(CameraDevice camera, int error) {

        }
    };
    //开始预览,主要是camera.createCaptureSession这段代码很重要,创建会话
    private void startPreview(CameraDevice camera) throws CameraAccessException {
        SurfaceTexture texture = mPreviewView.getSurfaceTexture();
        texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
        Surface surface = new Surface(texture);
        try {
            mPreviewBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
        mPreviewBuilder.addTarget(surface);
        camera.createCaptureSession(Arrays.asList(surface), mSessionStateCallback, mHandler);
    }

    private CameraCaptureSession.StateCallback mSessionStateCallback = new CameraCaptureSession.StateCallback() {

        @Override
        public void onConfigured(CameraCaptureSession session) {
            try {
                updatePreview(session);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onConfigureFailed(CameraCaptureSession session) {

        }
    };

    private void updatePreview(CameraCaptureSession session) throws CameraAccessException {
        session.setRepeatingRequest(mPreviewBuilder.build(), null, mHandler);
    }
}

我是天王盖地虎的分割线

源码:https://github.com/pinguo-yuyidong/Camera2

时间: 2024-10-10 00:11:46

Android -- Camera2(Android5.0)的相关文章

Android自定义组件系列【14】——Android5.0按钮波纹效果实现

今天任老师发表了一篇关于Android5.0中按钮按下的波纹效果实现<Android L中水波纹点击效果的实现>,出于好奇我下载了源代码看了一下效果,正好手边有一个Nexus手机,我结合实际效果看了一下,发现有一些地方和实际效果稍有不同,参考任老师的博文实现简单实现了一个重写View组件的代码,将全部代码贴出,如果有什么问题或者更好的方式请指出,在此再次感谢任老师的这篇博文. 转载请说明出处:http://blog.csdn.net/dawanganban 顺便在这里拉一下票,如果你觉得这篇文

Android Camera API2.0下全新的Camera FW/HAL架构简述

本文均属自己阅读源码的点滴总结,转账请注明出处谢谢. 欢迎和大家交流.qq:1037701636 email:gzzaigcn2[email protected] Software:系统源码Android5.1 前沿: 前面博文大多少总结的是Camera HAL1到HAL3的系统架构,但这些架构对于Camera APP开发来说依旧还是处于Camera API1.0的标准.而随着Camera3.HAL3.0等的不断更新,Google先是在Framework中更改了整个架构从而去匹配Camera A

Android5.0以上系统的移动网络开关

笔者近期遇到一个非常有意思的bug,贴出来和大家分享下. 那是一个温暖的早晨,阳光晒得人非常舒服.一封bug邮件像一片叶子飘到我的邮箱. 一番交流.笔者确认负责的Widget开关在Android5.0以上系统没有作用.相信非常多做过移动网络开关的朋友都知道.传统的方法是在ConnectivityManager中通过反射两个方法setMobileDataEnabled和getMobileDataEnabled来控制移动网络开和关的. /** * Gets the value of the sett

友情提醒:欲开发android5.0以上应用,请全部更新开发工具至最新

周末帮人完成一个项目,android5.0以上版本,谁知道被开发工具折腾的死去活来.我的开发环境是adt-bundle-windows-x86-20140702.zip版本,也是目前能找到的adt-bundle的最新版本.也升级至最新的adt和platform,但开发5.0的项目还是一堆错误: 错误1:动不动就报AndroidManifest.xml is missing的错误,为了解决这个问题每次都要将.android 和 开发空间里的.metadata,然后重启eclipse,真痛苦啊! 错

Android5.0之后的页面切换动画

Android5.0之后给我们开发者剩了好多的事情,为什么这么说呢?还记得刚开始的时候,Android里面的所有的动画都要我们开发者自己来写,现在不需要了,因为5.0之后自带了好多的动画,比如:按钮点击的动画.页面切换的动画(在android5.0之前想都不敢想的). 今天我着重讲一下页面之间的切换,目前5.0系统自带了三种动画方式:Explode(缩放).Fade(淡入淡出).Slide(滑动进入).下面就这三中方式进行介绍一下. 在讲解之前,现对于动画的方式进行介绍一下.通常,我们进行页面跳

Android5.0以上app进程保活的正确姿势

我的原文: http://blog.csdn.net/brycegao321/article/details/52312030 有图有真相,  亲测锤子T2.华为Mate8手机杀掉进程后能自启, 我设置的自启时间间隔为500ms(仅仅是为了测试).     首先要明确保活的概念: 1.非android核心进程(例如com.android.phone)都可以被干掉: 2.保活并不能真正的保证app进程不死,  而是能在被干掉后马上启动: Android系统按照进程的优先级分为: 1. 前台进程(F

ANDROID5.0触摸屏校准

1.校准原理: 1)首先生成校准用的参数,可以适用tslib生成校准参数,也可以使用校准app生成:使用校准app进行校准对使用者要求比较低,使用者可以不用学习复杂的命令:本文使用app方式 2)生成校准参数后,以后驱动每次接收到触摸事件就会使用校准参数进行校准 2.校准app 校准功能完全实现在在src目录里的MainActivity.java里,内容如下: package com.wss.calibrate2; import android.app.Activity;import andro

android5.0之toolBar

toolBar是android5.0之后提出的,可以简单的理解为ActionBar的升级版吧,在5.0之后,官方推荐使用ToolBar!下面开启ToolBar的正文(老样子,有问题请指正,有疑问,偶们共同讨论!嘎嘎......) ①toolBar是5.0之后提出的,那么低版本的该怎么办啊?老规矩咯,引入V7包'com.android.support:appcompat-v7:22.1.1',就是介个!(注意:下面的一些类都是V7包里的,不要写错了!!!) ②V7包引入之后,还是不可以直接使用to

android5.0开发必备版本和JDK环境配置

android5.0开发必备版本: JDK-1.8-x64; NDK-10-x64; ADT-5.0&4.0-x64; 谷歌代理: https://wen.lu/?gfe_rd=cr&ei=Ir7YU5XsOK3J8ge_24GgBQ&gws_rd=cr 也可用FQ软件:goagent,或FQ浏览器 goagent: https://github.com/goagent/goagent 配置地址:http://www.woshipm.com/it/13644.html JDK配置(