camera2的结构如下,主要是通过相机管理器(CameraManager)获得相机设备(CameraDevice),然后再开启一个控制相机的会话,最后发送 拍照、预览、录像等请求。

0 准备

1 新建工程,在一个Activity上

设置一个TextureView 用于 预览图片;

设置一个ImageView 用于 显示拍照结果;

设置一个 Button 用于触发拍照功能;

2 设置AndroidManifest.xml文件配置相机权限

<uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-feature android:name="android.hardware.camera2.full" />

I 实现预览功能

1.先创建好一个预览的容器textureView

textureView=findViewById(R.id.texture_view_camera2);

  1. 监听这个容器的状态,如果容器准备好了,就开启相机:
// 先准备一个监听器surfaceTextureListener=new TextureView.SurfaceTextureListener() {@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {texture_surface=new Surface(textureView.getSurfaceTexture());openCamera();}/.../};//绑定监听器textureView.setSurfaceTextureListener(surfaceTextureListener);

  1. 启动相机时,要创建一系列的回调函数,所以应该从后向前写代码:
private void openCamera() {// 1 创建相机管理器,调用系统相机cameraManager= (CameraManager) getSystemService(Context.CAMERA_SERVICE); // 2 准备 相机状态回调对象为后面用cam_stateCallback=new CameraDevice.StateCallback() {@Overridepublic void onOpened(@NonNull CameraDevice camera) {// 2.1 保存已开启的相机对象opened_camera=camera;try {// 2.2 构建请求对象(设置预览参数,和输出对象) requestBuilder = opened_camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); // 设置参数:预览requestBuilder.addTarget(texture_surface); // 设置参数:目标容器request = requestBuilder.build();//2.3 创建会话的回调函数,后面用cam_capture_session_stateCallback=new CameraCaptureSession.StateCallback() {@Override  //2.3.1  会话准备好了,在里面创建 预览或拍照请求public void onConfigured(@NonNull CameraCaptureSession session) {cameraCaptureSession=session;try {// 2.3.2 预览请求session.setRepeatingRequest(request,null,null);} catch (CameraAccessException e) {e.printStackTrace();}}};// 2.3 创建会话opened_camera.createCaptureSession( Arrays.asList(texture_surface), cam_capture_session_stateCallback,null);} catch (CameraAccessException e) {e.printStackTrace();}}/..../};// 4 检查相机权限 checkPermission();// 5 开启相机(传入:要开启的相机ID,和状态回调对象)try {cameraManager.openCamera(cameraManager.getCameraIdList()[0],cam_stateCallback,null);} catch (CameraAccessException e) {e.printStackTrace();}}

4 申请相机权限

private void checkPermission() {// 检查是否申请了权限if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CAMERA)){}else{ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},1);}}}

II 实现拍照功能

这段代码都是在 Activity的onCreate里面写的。

  1. 准备ImageReader用于监听并接收相机拍摄的图片
//B1. 准备工作:初始化ImageReaderimageReader = ImageReader.newInstance(1000  ,1000, ImageFormat.JPEG,2);

  1. 设置ImageReader的监听函数
//B2. 准备工作:设置ImageReader收到图片后的回调函数imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {@Overridepublic void onImageAvailable(ImageReader reader) {//B2.1 接收图片:从ImageReader中读取最近的一张,转成BitmapImage image= reader.acquireLatestImage();ByteBuffer buffer= image.getPlanes()[0].getBuffer();int length= buffer.remaining();byte[] bytes= new byte[length];buffer.get(bytes);image.close();bitmap = BitmapFactory.decodeByteArray(bytes,0,length);//B2.2 显示图片takephoto_imageView.setImageBitmap(bitmap);}},null);

  1. 保存ImageReader的Surface
//B3 配置:获取ImageReader的SurfaceimageReaderSurface = imageReader.getSurface();

  1. 设置相机的点击事件
//B4. 相机点击事件takephoto_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//B4.1 配置request的参数 拍照模式(这行代码要调用已启动的相机 opened_camera,所以不能放在外面try {requestBuilder_image_reader = opened_camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);} catch (CameraAccessException e) {e.printStackTrace();}requestBuilder_image_reader.set(CaptureRequest.JPEG_ORIENTATION,90);requestBuilder_image_reader.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);//B4.2 配置request的参数 的目标对象requestBuilder_image_reader.addTarget(imageReaderSurface );try {//B4.3 触发拍照cameraCaptureSession.capture(requestBuilder_image_reader.build(),null,null);} catch (CameraAccessException e) {e.printStackTrace();}}});

  1. 最后要记得在之前配置的session会话里面绑定,当前这个输出对象imageReaderSurface:
private void openCamera() {/.../cam_stateCallback=new CameraDevice.StateCallback() {@Overridepublic void onOpened(@NonNull CameraDevice camera) {/.../opened_camera.createCaptureSession( Arrays.asList(texture_surface,imageReaderSurface), cam_capture_session_stateCallback,null);}

这段功能的整体代码为:

@Overrideprotected void onCreate(Bundle savedInstanceState) {/......///B1. 准备工作:初始化ImageReaderimageReader = ImageReader.newInstance(1000  ,1000, ImageFormat.JPEG,2);//B2. 准备工作:设置ImageReader收到图片后的回调函数imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {@Overridepublic void onImageAvailable(ImageReader reader) {//B2.1 接收图片:从ImageReader中读取最近的一张,转成BitmapImage image= reader.acquireLatestImage();ByteBuffer buffer= image.getPlanes()[0].getBuffer();int length= buffer.remaining();byte[] bytes= new byte[length];buffer.get(bytes);image.close();bitmap = BitmapFactory.decodeByteArray(bytes,0,length);//B2.2 显示图片takephoto_imageView.setImageBitmap(bitmap);}},null);//B3 配置:获取ImageReader的SurfaceimageReaderSurface = imageReader.getSurface();//B4. 相机点击事件takephoto_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//B4.1 配置request的参数 拍照模式(这行代码要调用已启动的相机 opened_camera,所以不能放在外面try {requestBuilder_image_reader = opened_camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);} catch (CameraAccessException e) {e.printStackTrace();}requestBuilder_image_reader.set(CaptureRequest.JPEG_ORIENTATION,90);requestBuilder_image_reader.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);//B4.2 配置request的参数 的目标对象requestBuilder_image_reader.addTarget(imageReaderSurface );try {//B4.3 触发拍照cameraCaptureSession.capture(requestBuilder_image_reader.build(),null,null);} catch (CameraAccessException e) {e.printStackTrace();}}});}

III 相机的声明周期管理

1. 当activity不处于交互状态时释放相机

@Overrideprotected void onPause() {// 先把相机的session关掉if(cameraCaptureSession!=null){cameraCaptureSession.close();}// 再关闭相机if(null!=opened_camera){opened_camera.close();}// 最后关闭ImageReaderif(null!=imageReader){imageReader.close();}// 最后交给父View去处理super.onPause();}

2 当活动再次可以交互时开启相机

@Overrideprotected void onResume() {super.onResume();// 如果 textureView可用,就直接打开相机if(textureView.isAvailable()){openCamera();}else{// 否则,就开启它的可用时监听。textureView.setSurfaceTextureListener(surfaceTextureListener);}}

IV 预览和功能的完整代码为:

文件名 Camera2ApiActivity.java

package com.example.myapplication;import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.camera.camera2.impl.Camera2CaptureRequestBuilder;
import androidx.camera.core.CameraCaptureResult;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;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.graphics.SurfaceTexture;
import android.hardware.biometrics.BiometricManager;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.media.ImageReader;
import android.os.Bundle;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;import java.io.ByteArrayInputStream;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;public class Camera2apiActivity extends AppCompatActivity {TextureView textureView;TextureView.SurfaceTextureListener surfaceTextureListener;CameraManager cameraManager;CameraDevice.StateCallback cam_stateCallback;CameraDevice opened_camera;Surface texture_surface;CameraCaptureSession.StateCallback cam_capture_session_stateCallback;CameraCaptureSession.CaptureCallback still_capture_callback;CameraCaptureSession cameraCaptureSession;CaptureRequest.Builder requestBuilder;CaptureRequest.Builder requestBuilder_image_reader;ImageReader imageReader;Surface imageReaderSurface;Bitmap bitmap;CaptureRequest request;CaptureRequest takephoto_request;Button takephoto_btn;ImageView takephoto_imageView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_camera2api);textureView=findViewById(R.id.texture_view_camera2);takephoto_btn=findViewById(R.id.btn_camera2_takephoto);takephoto_imageView= findViewById(R.id.image_view_preview_image);surfaceTextureListener=new TextureView.SurfaceTextureListener() {@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {texture_surface=new Surface(textureView.getSurfaceTexture());openCamera();}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {return false;}@Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surface) {}};textureView.setSurfaceTextureListener(surfaceTextureListener);//B1. 准备工作:初始化ImageReaderimageReader = ImageReader.newInstance(1000  ,1000, ImageFormat.JPEG,2);//B2. 准备工作:设置ImageReader收到图片后的回调函数imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {@Overridepublic void onImageAvailable(ImageReader reader) {//B2.1 接收图片:从ImageReader中读取最近的一张,转成BitmapImage image= reader.acquireLatestImage();ByteBuffer buffer= image.getPlanes()[0].getBuffer();int length= buffer.remaining();byte[] bytes= new byte[length];buffer.get(bytes);image.close();bitmap = BitmapFactory.decodeByteArray(bytes,0,length);//B2.2 显示图片takephoto_imageView.setImageBitmap(bitmap);}},null);//B3 配置:获取ImageReader的SurfaceimageReaderSurface = imageReader.getSurface();//B4. 相机点击事件takephoto_btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//B4.1 配置request的参数 拍照模式(这行代码要调用已启动的相机 opened_camera,所以不能放在外面try {requestBuilder_image_reader = opened_camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);} catch (CameraAccessException e) {e.printStackTrace();}requestBuilder_image_reader.set(CaptureRequest.JPEG_ORIENTATION,90);requestBuilder_image_reader.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);//B4.2 配置request的参数 的目标对象requestBuilder_image_reader.addTarget(imageReaderSurface );try {//B4.3 触发拍照cameraCaptureSession.capture(requestBuilder_image_reader.build(),null,null);} catch (CameraAccessException e) {e.printStackTrace();}}});}private void openCamera() {cameraManager= (CameraManager) getSystemService(Context.CAMERA_SERVICE);  // 初始化cam_stateCallback=new CameraDevice.StateCallback() {@Overridepublic void onOpened(@NonNull CameraDevice camera) {opened_camera=camera;try {requestBuilder = opened_camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);requestBuilder.addTarget(texture_surface);request = requestBuilder.build();cam_capture_session_stateCallback=new CameraCaptureSession.StateCallback() {@Overridepublic void onConfigured(@NonNull CameraCaptureSession session) {cameraCaptureSession=session;try {session.setRepeatingRequest(request,null,null);} catch (CameraAccessException e) {e.printStackTrace();}}@Overridepublic void onConfigureFailed(@NonNull CameraCaptureSession session) {}};opened_camera.createCaptureSession( Arrays.asList(texture_surface,imageReaderSurface), cam_capture_session_stateCallback,null);} catch (CameraAccessException e) {e.printStackTrace();}}@Overridepublic void onDisconnected(@NonNull CameraDevice camera) {}@Overridepublic void onError(@NonNull CameraDevice camera, int error) {}};checkPermission();try {cameraManager.openCamera(cameraManager.getCameraIdList()[0],cam_stateCallback,null);} catch (CameraAccessException e) {e.printStackTrace();}}private void checkPermission() {// 检查是否申请了权限if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){if(ActivityCompat.shouldShowRequestPermissionRationale(this,Manifest.permission.CAMERA)){}else{ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},1);}}}@Overrideprotected void onResume() {super.onResume();// 如果 textureView可用,就直接打开相机if(textureView.isAvailable()){openCamera();}else{// 否则,就开启它的可用时监听。textureView.setSurfaceTextureListener(surfaceTextureListener);}}@Overrideprotected void onPause() {// 先把相机的session关掉if(cameraCaptureSession!=null){cameraCaptureSession.close();}// 再关闭相机if(null!=opened_camera){opened_camera.close();}// 最后关闭ImageReaderif(null!=imageReader){imageReader.close();}// 最后交给父View去处理super.onPause();}}

android 圆形相机预览拍照_Android Camera2 Api 实现预览和拍照相关推荐

  1. android 圆形相机预览拍照_Android多种方式实现相机圆形预览

    最终效果图如下: 一.为预览控件设置圆角 public RoundTextureView(Context context, AttributeSet attrs) { super(context, a ...

  2. android 圆形相机预览拍照_Android多种方式实现相机圆形预览的示例代码

    效果图如下: 一.为预览控件设置圆角 public RoundTextureView(Context context, AttributeSet attrs) { super(context, att ...

  3. android 读取mysql中的图片_Android 通过API获取数据库中的图片文件方式

    Overview 今天复习了一下Android 如何将我们数据库中图片获取出来,并且将其转换为bitmap进行显示. 开发环境以及技术 使用Visual Studio 2019 Android Stu ...

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

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

  5. android高仿微信拍照、多选、预览、删除(去除相片)相冊功能

    先声明授人与鱼不如授人与渔,仅仅能提供一个思路,当然须要源代码的同学能够私下有偿问我要源代码:QQ:508181017 工作了将近三年时间了,一直没正儿八经的研究系统自带的相冊和拍照,这回来个高仿微信 ...

  6. android surfaceview 大小_Android 使用Camera2 API采集视频数据

    Android 视频数据采集系列的最后一篇出炉了,和前两篇文章想比,这篇文章从系统API层面进行一些探索,涉及到的细节更多.初次接触 Camera2 API 会觉得它的使用有些繁琐,涉及到的类有些多, ...

  7. Android camera相机开发拍照功能

    在Android 5.0(SDK 21)中,Google使用Camera2替代了Camera接口.Camera2在接口和架构上做了巨大的变动,但是基于众所周知的原因,我们还必须基于 Android 4 ...

  8. 详记Android打开相机拍照流程

    写在前面 本文并不是基于Camera2的,所以想要了解Camera2的同学可以先散了.文题加了详记二字,因为相机整个打开的流程的确是比较复杂的,稍有疏忽可能就会引发一系列问题.我也是看了一下Andro ...

  9. Android Camera2 API和拍照与录像过程

    简介: Android 5.0开始出现了新的相机Camera 2 API,用来替代以前的camera api. Camera2 API不仅提高了android系统的拍照性能,还支持RAW照片输出,还可 ...

  10. Android最新相机(Camera)拍照、拍视频全面总结

    介绍 利用系统相机 调用系统相机拍照 获取小图标 获取全尺寸图片 添加到相册 系统相机拍视频 自定义相机 自定义相机拍照 监测设备是否有相机可使用 利用SurfaceView创建拍照时预览界面 拍照并 ...

最新文章

  1. python语言标识符首字符不能是_Python语言标识符的命名规定,首字符不能是( )...
  2. Middleware(中间件)
  3. 蓝桥杯 试题 基础练习 十六进制转十进制——5行代码AC
  4. 宅男程序员给老婆的计算机课程之4:SQL vs NoSQL
  5. 一加、OPPO官宣合并,“父子团圆”能否拯救一加?
  6. ×××数据库导数据ora-01400错误小计
  7. Mathtype 免安装 | office自带UnicodeMath和LaTeX编辑功能
  8. lightshot截图工具的安装及使用
  9. 老罗Android开发视频分享
  10. 正宇丨有钱,把日子过好;没钱,把心情过好
  11. A hybrid CNN-LSTM model for typhoon formation
  12. SQL如何修改表中的结构
  13. 测试结果类型为: ESTJ
  14. 用ul、li做横向导航
  15. my fav html
  16. 股份有限公司章程记载事项有哪些
  17. 转:动态规划题目分类
  18. MAC MySql 安装(详细步骤)
  19. fastreport 打印有 demo version字样_噬神者3免费试玩DEMO试玩 | 伊迪丝芬奇的记忆将登陆SWITCH...
  20. js Date中的T和Z (实用,赞)

热门文章

  1. bzoj 4537: [Hnoi2016]最小公倍数 分块+并查集
  2. MvvmCross框架在XamarinForms中的使用入门
  3. NSArray去除重复元素
  4. Activity保存状态saving activity state和onPause()
  5. 右键菜单 GenericMenu
  6. Careercup - Microsoft面试题 - 5680049562845184
  7. [转载]Oracle Minus关键字
  8. java面向接口编程详解
  9. ErrorPageRegistrar根据不同的错误类型显示网页
  10. redis数据类型之Set