camera2 是21之后的api用于代替Camera,提供更加牛X的对相机hardware操作的api

参考资料:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0428/2811.html
http://www.tuicool.com/articles/6b67Nra

此篇笔记主要是记录打开预览界面
后面会记录Camera打开相机预览的代码,对比一下

界面布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><com.arvin.camera3.view.AutoFitTextureView
        android:id="@+id/surface"android:layout_width="wrap_content"android:layout_height="wrap_content" /><Button
        android:id="@+id/capturebtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:text="拍照" /><ImageView
        android:id="@+id/preview"android:layout_width="120dp"android:layout_height="120dp"android:layout_alignParentBottom="true" /></RelativeLayout>

AutoFitTextureView 继承自 TextureVeiw

1.首先要初始化view,就是一些findviewbyid

2.示例代码是在onResume中,能否有更好方式????

if (surfaceView.isAvailable()) {// FIXME: 2016/6/13try {openCamera(surfaceView.getWidth(), surfaceView.getHeight());} catch (Exception e) {e.printStackTrace();}
} else {surfaceView.setSurfaceTextureListener(mSurfaceTextureListener);
}

surfaceView即TextureView

判断TextureView状态
可用,打开相机,否则设置相应的回调

先看打开相机的代码

private void openCamera(int width, int height) throws Exception {Activity activity = getActivity();CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);if (mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {manager.openCamera(mCameraId,deviceStateCallback,mPreviewHandler );}
}

首先调用getSystemService(Context.CAMERA_SERVICE),拿到CameraManager实例,
注:Api 21 新增的,无兼容包,估计也不会发布兼容包吧,21之后 Camera已弃用
然后通过CameraManager实例的 openCamera()方法打开相机预览
我们看下openCamera的声明

@RequiresPermission(android.Manifest.permission.CAMERA)
public void openCamera(@NonNull String cameraId,@NonNull final CameraDevice.StateCallback callback, @Nullable Handler handler)throws CameraAccessException {if (cameraId == null) {throw new IllegalArgumentException("cameraId was null");} else if (callback == null) {throw new IllegalArgumentException("callback was null");} else if (handler == null) {if (Looper.myLooper() != null) {handler = new Handler();} else {throw new IllegalArgumentException("Handler argument is null, but no looper exists in the calling thread");}}openCameraDeviceUserAsync(cameraId, callback, handler);
}

@RequiresPermission(android.Manifest.permission.CAMERA)

需要camera权限,在camera声明,android 6.0之后需要请求,属于runtime permission

需要传入三个参数
cameraId : “0”表示后置摄像头,“1”表示前置摄像头
callback : CameraDevice.StateCallback 相机状态回调
注:CameraDevice 实例代表一个相机
handler : hanlder

回头看如果TextureView不可用的状态下

surfaceView.setSurfaceTextureListener(mSurfaceTextureListener);

看下 mSurfaceTextureListener是个什么东西

private final TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {try {openCamera(width, height);} catch (Exception e) {e.printStackTrace();}}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {return false;}@Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surface) {}
};

这个有点和SurfaceView的回调相似了
设置回调,然后当surface可用的时候openCamera(),回到上面的流程去了
包含四个方法,分别对应可用,尺寸发生变化,TextureView销毁,以及更新的时候回调

继续看manager.openCamera();
已经说了第一个参数camreaId,“0”代表后置摄像头,“1”代表前置摄像头
第二个参数CameraDevice.StateCallback, 直接看

CameraDevice.StateCallback deviceStateCallback = new CameraDevice.StateCallback() {@Overridepublic void onOpened(CameraDevice camera) {mCameraOpenCloseLock.release();mCameraDevice = camera;try {createCameraPreviewSession();} catch (CameraAccessException e) {e.printStackTrace();}}@Overridepublic void onDisconnected(CameraDevice camera) {mCameraOpenCloseLock.release();camera.close();mCameraDevice = null;}@Overridepublic void onError(CameraDevice camera, int error) {mCameraOpenCloseLock.release();camera.close();mCameraDevice = null;Toast.makeText(getActivity(), "onError,error--->" + error, Toast.LENGTH_SHORT).show();}
};

通过代码可知,CameraDevice.StateCallback 提供了三个回调方法,分别对应于camrea打开,失去连接,打开错误的时候回调,
在打开的时候会调用createCameraPreviewSession() ,看一下方法定义

private void createCameraPreviewSession() throws CameraAccessException {initSurface();mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);mPreviewBuilder.addTarget(mSurface);mCameraDevice.createCaptureSession(Arrays.asList(mSurface), mCaptureSessionStateCallback, mPreviewHandler);
}private void initSurface() {SurfaceTexture sufaceTexture = surfaceView.getSurfaceTexture();assert sufaceTexture != null;sufaceTexture.setDefaultBufferSize(surfaceView.getWidth(), surfaceView.getHeight());mSurface = new Surface(sufaceTexture);
}

首先通过TextureView的getSurfaceTexture() 拿到 对应 SurfaceTexture 是不是SurfaceView的getSurfaceHolder()很像
设置显示大小,创建Surface实例
之后,调用 CameraDevice createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW) 创建预览请求
并设置target, CaptureRequest.Builder addTarget(Surface surface)
然后调用CameraDevice createCaptureSession(),创建一个相机回话

createCaptureSession()需要传入三个参数
看下声明

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

List outputs 我的理解是预览的输出载体列表,在上面的代码中,我们传入了new Surface(TextureView.getSurface()) 对象
ImageReader 也有 getSurface()方法,ImageReader也可以作为输出载体

第二个参数CameraCaptureSession.StateCallback 摄像头采集状态回调
直接看代码

private CameraCaptureSession.StateCallback mCaptureSessionStateCallback = new CameraCaptureSession.StateCallback() {@Overridepublic void onConfigured(CameraCaptureSession session) {if (null == mCameraDevice) {return;}mSession = session;mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);try {session.setRepeatingRequest(mPreviewBuilder.build(), mSessionCaptureCallback, mPreviewHandler);} catch (CameraAccessException e) {e.printStackTrace();}}@Overridepublic void onConfigureFailed(CameraCaptureSession session) {}};

设置拍摄模式,这里设置了连拍,flash,其他的模式嘛,我也不清楚了

mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);session.setRepeatingRequest(mPreviewBuilder.build(), mSessionCaptureCallback, mPreviewHandler);

设置重复请求,字面上这么理解

同样是三个参数
第一个是CaptureRequest.Builder buildI() 这个是前面采集请求builder 通过CameraDevice createCaptureRequest创建的
第二个是摄像头采集回话采集状态的回调

private CameraCaptureSession.CaptureCallback mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() {@Overridepublic void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {super.onCaptureCompleted(session, request, result);}@Overridepublic void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) {super.onCaptureProgressed(session, request, partialResult);}
};

包含两个状态,采集进行,采集完成
可以在这里面去做处理,
贴上一段代码

private CameraCaptureSession.CaptureCallback mSessionCaptureCallback = new CameraCaptureSession.CaptureCallback() {@Overridepublic void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {mSession = session;if (!PreferenceHelper.getCameraFormat(getActivity()).equals("DNG")) {checkState(result);}}@Overridepublic void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) {mSession = session;if (!PreferenceHelper.getCameraFormat(getActivity()).equals("DNG")) {checkState(partialResult);}}private void checkState(CaptureResult result) {
//            mFrameBitmap = mPreviewView.getBitmap();
//            mMainHandler.sendEmptyMessage(1);switch (mState) {case STATE_PREVIEW:// NOTHINGbreak;case STATE_WAITING_CAPTURE:int afState = result.get(CaptureResult.CONTROL_AF_STATE);Log.i("checkState", "afState--->" + afState);if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState|| CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED == afState || CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED == afState) {Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);Log.i("checkState", "进来了一层,aeState--->" + aeState);if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {Log.i("checkState", "进来了第二层");mState = STATE_TRY_DO_CAPTURE;doStillCapture();} else {mState = STATE_TRY_CAPTURE_AGAIN;tryCaptureAgain();}}break;case STATE_TRY_CAPTURE_AGAIN:Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);if (aeState == null ||aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {mState = STATE_TRY_DO_CAPTURE;}break;case STATE_TRY_DO_CAPTURE:aeState = result.get(CaptureResult.CONTROL_AE_STATE);if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {mState = STATE_TRY_DO_CAPTURE;doStillCapture();}break;}}
};

至此,打开相机预览的代码就结束了,后续比如拍照,录像什么的以后再分析啦,这里的api还没在学习中

最后附上Camera打开预览的代码,感觉要简单好多呀

//布局文件
<SurfaceViewandroid:id="@+id/surface"android:layout_width="match_parent"android:layout_height="match_parent" />Camera camera;
surfaceView = (SurfaceView) findViewById(R.id.surface);
holder = surfaceView.getHolder();
holder.addCallback(this);  //设置回调@Override
public void surfaceCreated(SurfaceHolder holder) {camera = Camera.open();try {camera.setPreviewDisplay(holder);} catch (IOException e) {e.printStackTrace();}camera.startPreview();
}//将camera预览界面绑定到SurfaceView
//startPreview()@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Override
public void surfaceDestroyed(SurfaceHolder holder) {}

代码是不是比camera2简单多了,不过这个预览界面挺难看的,其他设置也没有仔细研究,用到的时候再说吧

文中参考了
Android实战技巧之三十三:android.hardware.camera2使用指南
再此对原作者表示感谢

Camera2 打开相机预览界面相关推荐

  1. Android Camera API/Camera2 API 相机预览及滤镜、贴纸等处理

    Android Lollipop 增加了Camera2 API,并将原来的Camera API标记为废弃了.相对原来的Camera API来说,Camera2是重新定义的相机 API,也重构了相机 A ...

  2. Android相机预览页面被压缩和拉伸问题

    最近公司要求在原有的项目中添加一个扫码登录的功能,在调试好相机之后,发现相机返回到Surfaceview页面上的预览图片,与我们现实中物品的比例并不相同,在一块正方形的Surfaceview中,预览界 ...

  3. Android Camera2 相机预览、获取数据

    Camera2简要说明 在Google 推出Android 5.0的时候, Android Camera API 版本升级到了API2(android.hardware.camera2),大幅提高了A ...

  4. 【Android -- 相机】Camera2 实现拍照 预览功能

    前言 上篇文章,我们已经用 Camera1 实现了预览和拍照的功能,但也说到,在API21的时候,Camera1已经被标注为弃用,因为它的API功能和灵活性满足不了现在日益复杂的相机开发了,所以在 A ...

  5. Android Camera2相机预览画面放大缩小(数码变焦DigitalZoom)功能实现

    一.前言 Android自定义相机开发中,常常会有通过手势放大或缩小相机预览画面的需求,即数码变焦DigitalZoom. 二.接口说明 1. 获取最大的放大倍数 float maxZoom = mC ...

  6. Camera2打开相机,建立会话,并监听相机流(以拍照为例)

    Camera2打开相机,建立会话,并监听相机流(以拍照为例) 获取 CameraManager 通过 CameraManager.openCamera() 方法打开相机,监听回调,获取 CameraD ...

  7. android 使用 surfaceView 获取 camera 预览界面图像数据

    在android中,通过相机获取预览界面的需求似乎很变态,好像也没有什么使用场景.但是,有一个场景需要获取预览界面的图像,就是扫码,比如微信,支付宝的扫一扫,就是需要获取预览界面的图像数据的. 实现逻 ...

  8. Android stdio 实时获取相机预览图像(详细)

    activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...

  9. android surfaceview camera,android – 如何在SurfaceView上显示相机预览?

    要使用Camera2 API从相机显示预览,您应该执行以下步骤: >获得使用相机设备的权限 >使用CameraManager打开与相机的连接 准备表面预览 >使用打开的相机设备和所需 ...

最新文章

  1. 播放视频一会,出错并自动关闭
  2. android miui9.0改装条例,安卓的通知适配(更新至9.0)
  3. C++来了,详细知识点思维导图!
  4. logstash+elasticsearch +kibana 日志管理系统
  5. Git:解决Git向码云中push文件报错:! [rejected] master -> master (fetch first)
  6. python实现取出一个列表或者多个列表中的公共前缀
  7. PDF编辑器哪个好,怎么在PDF中添加图片
  8. 节约里程算法java实现
  9. oracle10安装完成之后测试,RHEL4U4和RHEL5安装oracle10g(测试过绝对可以成功)
  10. MLI_09 HMM(隐马尔可夫模型)
  11. 数据挖掘十大算法---朴素贝叶斯
  12. mysql数据库三表联查
  13. 强化学习王者荣耀Ai的搭建
  14. 阿里品牌数据品牌银行分析师认证真题资料库整理答案
  15. 整理了4大类22种图表,不用担心用错统计图表,分析不出东西了
  16. python3数据处理(一)-- 解析XML,Excle文件
  17. ubuntu系统安装完nvidia显卡驱动后黑屏,不能进入系统
  18. SugarCRM 自定义选择按钮
  19. 树莓派上Python实现TSL2561采样光照强度
  20. VS Code下git的ca-bundle.crt问题

热门文章

  1. DataView 构造
  2. spring整合mongoDB 和 Redis 极简入门
  3. JavaSocket编程之Netty框架线程模型
  4. js通过class获取元素
  5. IBM服务器硬盘灯不正常闪烁的解决办法(新硬盘绿灯闪烁)
  6. Omni Core v0.11.0 rpc-api
  7. Apache Activemq-JMS了解+mq指定JDK
  8. Linux正确删除软链接
  9. idea安装阿里巴巴java规范插件(代码质量管理)安装和使用
  10. 量子计算核心突破!Shor算法实现或使密码成摆设