gitee 链接:
通过 captureBurst 实现连拍
拍完的图片放在 /data/data/com.example.burstcapture/files/
图片路径
连拍的具体实现代码在 BurstCapture.java 、BurstCaptureExpo.java、BurstCaptureFocus.java中,调用在 MainActivity.java中,调用方式很简单
连拍调用方式

普通连拍 直接创建 BurstCapture 这个类,在这个类的构造方法中会发 request

注意 :下面代码中的照片保存的路径 /data/data/com.example.burstcapture/files/ 中的 files 文件夹是我自己创建的,你需要自己手动创建下。

下面代码即可实现连拍:

mImageReader.setOnImageAvailableListener(mReaderImgListener, null);
mStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
mStillBuilder.addTarget(mImageSurface);
CaptureRequest request = mStillBuilder.build();
List<CaptureRequest> requests = new ArrayList<>();
// 改变下面的i的取值范围就可以改变连拍的数量
for(int i=0;i<3;i++)
    requests.add(request);
mCaptureSession.captureBurst(requests, null, null);
ImageReader.OnImageAvailableListener mReaderImgListener = new ImageReader.OnImageAvailableListener() {
    @Override
    public void onImageAvailable(ImageReader reader) {
        writeImageToFile();
private void writeImageToFile() {
    String filePath = "/data/data/com.example.burstcapture/files/"+imageIndex+".jpg";
    imageIndex++;
    Image image = mImageReader.acquireNextImage();
    if (image == null) {
        return;
    ByteBuffer byteBuffer = image.getPlanes()[0].getBuffer();
    byte[] data = new byte[byteBuffer.remaining()];
    byteBuffer.get(data);
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(new File(filePath));
        fos.write(data);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fos.close();
            fos = null;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            image.close();
            image = null;

不同曝光时间的连拍:

mStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
mStillBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
// 把AE关掉,通过手动的方式控制AE
mStillBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_OFF);
private void takePicturePrecapture(){
    final CaptureRequest.Builder precaptureBuilder;
    try {
        precaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        precaptureBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
        precaptureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
        precaptureBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
        precaptureBuilder.addTarget(mPreViewSurface);
        int sequenceId = mCaptureSession.capture(precaptureBuilder.build(), null, null);
        sequenceId = mCaptureSession.setRepeatingRequest(precaptureBuilder.build(), null, null);
        precaptureBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);
        sequenceId = mCaptureSession.capture(precaptureBuilder.build(), mMCaptureCallback, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
MCaptureCallback mMCaptureCallback = new MCaptureCallback();
    private class  MCaptureCallback extends CameraCaptureSession.CaptureCallback {
        @Override
        public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
            Log.e("TAG", "============================== onCaptureCompleted: ");
            Integer ae_state = result.get(CaptureResult.CONTROL_AE_STATE);
            if (ae_state == CaptureResult.CONTROL_AE_STATE_PRECAPTURE){
                try {
                    mStillBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
                    mStillBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CaptureRequest.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
                    // 把AE关掉,通过手动的方式控制AE
                    mStillBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_OFF);
                    mStillBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH); // just in case
                    mStillBuilder.addTarget(mImageSurface);
                    CaptureRequest captureRequest = mStillBuilder.build();
                    List<CaptureRequest> requests = new ArrayList<>();
                    Range<Integer> iso_range = mCharacteristics.get(CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE); // may be null on some devices
                    int iso = 800;
                    // see https://sourceforge.net/p/opencamera/tickets/321/ - some devices may have auto ISO that's
                    // outside of the allowed manual iso range!
                    iso = Math.max(iso, iso_range.getLower());
                    iso = Math.min(iso, iso_range.getUpper());
                    mStillBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, iso );
                    mStillBuilder.set(CaptureRequest.SENSOR_FRAME_DURATION, 1000000000L/30);
                    int n_half_images = 3/2;
                    long base_exposure_time = 22222000;
                    long min_exposure_time = base_exposure_time;
                    long max_exposure_time = base_exposure_time;
                    float expo_bracketing_stops = 2.0f;
                    final double scale = Math.pow(2.0, expo_bracketing_stops/(double)n_half_images);
                    Range<Long> exposure_time_range = mCharacteristics.get(CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE); // may be null on some devices
                    if( exposure_time_range != null ) {
                        min_exposure_time = exposure_time_range.getLower();
                        max_exposure_time = exposure_time_range.getUpper();
                    // darker images
                    for(int i=0;i<1;i++) {
                        long exposure_time = base_exposure_time;
                        if( exposure_time_range != null ) {
                            double this_scale = scale;
                            for(int j=i;j<n_half_images-1;j++)
                                this_scale *= scale;
                            exposure_time /= this_scale;
                            if( exposure_time < min_exposure_time )
                                exposure_time = min_exposure_time;
                            mStillBuilder.setTag(new String("darker images"));
                            mStillBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, exposure_time);
                            Log.e("TAG", " 0000000000 ");
                            requests.add( mStillBuilder.build() );
                    Log.e("666666", "scale = "+scale +" base_exposure_time = "+base_exposure_time+" exposure_time = "+base_exposure_time/scale);
                    mStillBuilder.setTag(new String("base image"));
                    // base image
                    mStillBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, base_exposure_time);
                    requests.add( mStillBuilder.build() );
                    // lighter images
                    for(int i=0;i<n_half_images;i++) {
                        long exposure_time = base_exposure_time;
                        if( exposure_time_range != null ) {
                            double this_scale = scale;
                            for(int j=0;j<i;j++)
                                this_scale *= scale;
                            exposure_time *= this_scale;
                            if( exposure_time > max_exposure_time )
                                exposure_time = max_exposure_time;
                            mStillBuilder.setTag(new String("lighter images"));
                            mStillBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, exposure_time);
                            Log.e("TAG", " 1111111111111 ");
                            requests.add( mStillBuilder.build() );
                    Log.e("TAG", "n_half_images = "+n_half_images );
                    Log.e("666666", "scale = "+scale +" exposure_time = "+(scale * base_exposure_time)+" base_exposure_time = "+base_exposure_time);
//            mCaptureSession.stopRepeating();
                    mCaptureSession.captureBurst(requests, null, null);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
            super.onCaptureCompleted(session, request, result);
                    gitee 链接:通过 captureBurst 实现连拍拍完的图片放在 /data/data/com.example.burstcapture/files/连拍的代码在 BurstCapture.java 中,调用方式很简单直接创建 BurstCapture 这个类,在这个类的构造方法中会发 request下面代码即可实现连拍:mImageReader.setOnImageAvailableListener(mReaderImgListener, null);mStillBuilder 
public class SnapPicActivity extends Activity 
  implements SurfaceHolder.Callback{
final private static String STILL_IMAGE_FILE = "capture.jpg";
private
				
~转载请注明http://blog.csdn.net/u013015161/article/details/46921257介绍这几天,写了一个自定义照相机的demo,支持连续照和摄像头切换。由于自己以前没接触过相关的编程,也算是一个学习的过程,在这里做一下记录,同时也分享出来,并附上源码和工程。 效果如图: 左上角switch切换摄像头,右边snap按钮进行照。一般流程Android
前段时间在做一个Android项目,其中涉及到需要实现“后台”静默打开前置摄像头连续照进行人脸检测。 尝试过网上各种方法,主要做法就是将预览透明+变小(0.1x0.1),但是这种做法并不能实现所谓的“后台”效果,你只能在一个透明界面啥也干不了,不能进行交互,或者出现闪退等问题。 这个问题基本困扰了我一个多月,在此感谢https://blog.csdn...
实现视频的循环录制,主要讲用到的接口,和实现的思路 ---------------------------------------------------------------------------------- 1、视频的录制需要用到MediaRecorder类,对新new的MediaRecorder类的对象mMediaRecorder设置 setOnInfoListener...
ProCamera ProCamera是一款基于Camera2 API的相机,实现了相机的常用功能,力求不断挖掘Camera2的巨大潜力,锻造一款在功能和设计上完美的相机产品。 相机常用功能:自动对焦/测光,手动对焦/测光,前后摄像头切换,切换闪光灯模式,使用HDR,添加GPU滤镜,拍摄比例调节,延时摄影,录制视频。 图像处理相关:点击左下角按钮会进入相册,选取相册后可进行图像处理。包括:裁剪,滤镜,字幕,印记,对比度等的调节。 即将上线功能: 30fps高清连实现焦点和测光点的手动分离,0延迟快门拍摄,raw格式的图片输出、调节awb/iso/ae。 针对人像拍摄,提供面部识别功能,识别成功后自动进行美颜。 设置界面相关功能:包括设置九宫格、图片数字签名(位置、时间、版权、字号、颜色)、水平校准、图片质量设置、拍摄视频质量设置、实时直方图、防手抖、 图像处理:会逐步向snapseed靠拢,并结合vsco、prisma这些有趣的应用进行改进。 如果图像中人像占用了大部分空间,将采用类似于美图的以美颜为主的图像处理。 简单使用方法 在xml中引入Camera2
我们上次介绍了利用Camera进行照,实现自定义相机的效果。这一次我们基于上一次的项目,实现效果。上次博客路径奉上 Android中自定义相机Camera使用 好了,我们正题开始。 基于上一次的项目,首先我们添加一些需要的全局变量。 //连属性 private boolean isShooting = false;//是否正在连 private int shooting_num = 0;//已经拍摄的相片数量 private ArrayList<String> mShooti
在此处说明一点,本例子实现的是三连,通过异步任务类实现的存储,最重要的一点:Camera的回调是异步方式的,三连不能够使用简单的for循环,我在这里使用的递归方法。 1.CameraPreview。java public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { priva
### 回答1: Android Camera2 API是Android系统提供的一种新的相机框架,用于实现相机预览和采集功能。Camera2 API可以提供更强大、更灵活的相机控制和图像处理能力。 相比于传统的Camera API,Camera2 API具有以下优势: 1. 能够同时管理多个相机设备:Camera2 API支持同时管理多个相机设备,包括前置摄像头、后置摄像头、深度摄像头等,可以方便地进行相机切换和管理。 2. 提供更灵活的相机控制:Camera2 API提供了更丰富的相机控制选项,可以精确地设置曝光时间、ISO值、焦距等参数,以便于用户根据不同的拍摄场景进行调整。 3. 支持原生的相机预览和采集:Camera2 API提供了对原生的预览和采集数据的支持,可以更高效地获取图像数据,用户可以利用这些数据进行实时的图像处理或者保存。 4. 支持原生的相机回调:Camera2 API提供了原生的相机回调接口,用户可以通过设置回调函数来实时获取相机的状态和图像数据,从而实现一些特殊的相机功能,如实时人脸检测、连等。 总之,Android Camera2 API提供了更强大、更灵活的相机功能,可以满足开发者对相机预览和采集的各种需求。无论是在智能手机、平板电脑还是其他移动设备上,都可以通过Camera2 API来实现高质量的相机应用。 ### 回答2: Android Camera 2是Android系统中用于处理相机功能的全新API。相较于之前的Camera API,Camera 2更加强大和灵活,提供了更多的功能和优化。 在Android Camera 2中,预览采集是通过创建一个CameraDevice实例来实现的。首先,需要获取相机的相关信息,例如相机的ID、参数等。然后,通过调用CameraManager的openCamera方法来打开指定ID的相机。 在相机打开后,可以通过创建一个CaptureRequest.Builder对象来配置相机的预览设置。可以设置预览的目标Surface、预览图像的尺寸、帧率等。然后,通过调用createCaptureSession方法,传入预览的目标Surface和一个CameraCaptureSession.StateCallback来创建一个预览会话。 在预览会话创建后,可以调用setRepeatingRequest方法来开始预览。Camera2会自动将预览帧数据传输到指定的Surface上,并在Surface上更新预览图像。同时,可以通过设置回调函数来处理预览数据,例如实时显示预览图像、进行进一步的图像处理等。 在预览过程中,还可以根据需要调整相机的参数,例如调整曝光度、焦距、白平衡等。通过创建新的CaptureRequest.Builder对象并设置相应参数,然后调用Session的setRepeatingRequest方法,可以实现动态调整相机参数。 总而言之,Android Camera 2提供了更强大和灵活的方式来实现相机预览采集。通过合理地使用Camera2的API,我们可以轻松地实现各种功能,例如实时预览、图像处理、动态调整参数等。 ### 回答3: Android Camera2预览采集是通过使用Android操作系统的Camera2 API来实现的一种方式。Camera2 API是Android 5.0(Lollipop)版本引入的相机框架,它提供了更多的功能和灵活性,用于控制和管理Android设备上的相机。 使用Camera2 API进行预览采集是一种相对较新和高级的方法,相比传统的Camera API,Camera2 API提供了更多的控制选项和功能,以及更好的性能和稳定性。 通过Camera2 API,我们可以实时地从Android设备的摄像头获取图像,并将图像传输到屏幕上进行实时预览。预览采集可以在应用程序中使用,例如用于视频通话、照、视频录制等场景。 Camera2 API的预览采集过程主要涉及以下步骤: 1. 获取相机设备:通过CameraManager类获取设备的摄像头列表,并选择要使用的摄像头设备。 2. 创建相机会话:使用CameraDevice类进行连接和建立与相机设备的会话。 3. 创建预览请求:使用CaptureRequest.Builder类创建一个预览请求,并设置相应的参数,例如预览尺寸、帧率等。 4. 创建预览会话:使用CameraDevice类创建预览会话,并将预览请求设置为预览会话的目标。 5. 开启预览:将预览会话设置为活动状态,相机将开始实时地捕获图像,并通过指定的Surface进行预览。 通过这些步骤,我们可以在Android设备上实现相机预览采集功能,并根据需要进行自定义设置和扩展。预览采集可以进一步应用于更多的相机应用场景,例如人脸识别、图像处理等。