public class SurfaceViewActivity extends AppCompatActivity {String TAG="SurfaceViewActivity_AA";TextureView textureView=null;CaptureRequest.Builder mCaptureRequestBuilder;CaptureRequest  mCaptureRequest;Surface mSurfacePrevew; //预览的surfaceImageReader  mImageReader;private Size mPreviewSize;private Size mCaptureSize;CameraDevice  mCameraDevice;private CameraCaptureSession mCameraCaptureSession;;private static final SparseIntArray ORIENTATION = new SparseIntArray();static {ORIENTATION.append(Surface.ROTATION_0, 90);ORIENTATION.append(Surface.ROTATION_90, 0);ORIENTATION.append(Surface.ROTATION_180, 270);ORIENTATION.append(Surface.ROTATION_270, 180);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_surface_view);textureView=(TextureView)findViewById(R.id.svPhoto);textureView.setSurfaceTextureListener(new SurfaceTextureListener());findViewById(R.id.btPhoto).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {capture();}});}@TargetApi(Build.VERSION_CODES.LOLLIPOP)private void OpenCamera(){try {Log.e(TAG,"OpenCamera");CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);try {//遍历所有摄像头for (String cameraId: manager.getCameraIdList()) {CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);//默认打开后置摄像头if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT)continue;//获取StreamConfigurationMap,它是管理摄像头支持的所有输出格式和尺寸StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);mPreviewSize = getOptimalSize(map.getOutputSizes(SurfaceTexture.class), mPreviewSize.getWidth(), mPreviewSize.getHeight());//获取相机支持的最大拍照尺寸mCaptureSize = Collections.max(Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)), new Comparator<Size>() {@Overridepublic int compare(Size lhs, Size rhs) {return Long.signum(lhs.getWidth() * lhs.getHeight() - rhs.getHeight() * rhs.getWidth());}});break;}} catch (CameraAccessException e) {e.printStackTrace();}manager.openCamera(manager.getCameraIdList()[0], new CameraState(), null);}catch (Exception ex){}}class CameraState extends CameraDevice.StateCallback {@Overridepublic void onOpened(CameraDevice camera) {mCameraDevice = camera;try {setupImageReader();SurfaceTexture mSurfaceTexture = textureView.getSurfaceTexture();//设置TextureView的缓冲区大小mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());//获取Surface显示预览数据mSurfacePrevew = new Surface(mSurfaceTexture);//需要同时增加预览和拍照的 Surfacecamera.createCaptureSession(Arrays.asList(mSurfacePrevew,mImageReader.getSurface()), new CameraSessionState(), null);}catch (Exception ex){}}@Overridepublic void onDisconnected(CameraDevice camera) {Log.e(TAG,"CameraState ==> onDisconnected camera.id="+camera.getId());}@Overridepublic void onError(CameraDevice camera, int error) {Log.e(TAG,"CameraState ==> handleMessage camera.id="+camera.getId()+"  error="+error);}@Overridepublic void onClosed(CameraDevice camera) {super.onClosed(camera);Log.e(TAG,"CameraState ==> onClosed camera.id="+camera.getId());//当调用CameraDevice.close()关闭相机设备后会回调此方法。camera为别关闭的相机设备。//该方法被回调执行后,任何尝试调用camera相关的操作都会失败,并且抛出一个IllegalStateException异常}}class CameraSessionState extends   CameraCaptureSession.StateCallback{@Overridepublic void onConfigured(CameraCaptureSession session) {Log.e(TAG, "CameraSessionState onConfigured");try {//创建CaptureRequestBuilder,TEMPLATE_PREVIEW比表示预览请求mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);//设置Surface作为预览数据的显示界面mCaptureRequestBuilder.addTarget(mSurfacePrevew);//创建捕获请求mCaptureRequest = mCaptureRequestBuilder.build();mCameraCaptureSession = session;//设置反复捕获数据的请求,这样预览界面就会一直有数据显示mCameraCaptureSession.setRepeatingRequest(mCaptureRequest, null, null);} catch (CameraAccessException e) {e.printStackTrace();}}@Overridepublic void onConfigureFailed(CameraCaptureSession session) {Log.e(TAG,"CameraSessionState onConfigureFailed");}}class SurfaceTextureListener implements TextureView.SurfaceTextureListener{@Overridepublic void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {Log.e(TAG,"SurfaceTextureListener===> onSurfaceTextureAvailable");mPreviewSize=new Size(width,height);OpenCamera();}@Overridepublic void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {Log.e(TAG,"SurfaceTextureListener===> onSurfaceTextureSizeChanged");}@Overridepublic boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {Log.e(TAG,"SurfaceTextureListener===> onSurfaceTextureDestroyed");return false;}@Overridepublic void onSurfaceTextureUpdated(SurfaceTexture surface) {// Log.e(TAG,"SurfaceTextureListener===> onSurfaceTextureUpdated");}}private void capture() {Log.e(TAG,"capture===>  ");try {//首先我们创建请求拍照的CaptureRequestif(mCameraDevice==null)return;final CaptureRequest.Builder mCaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);//获取屏幕方向int rotation = getWindowManager().getDefaultDisplay().getRotation();//设置CaptureRequest输出到mImageReadermCaptureBuilder.addTarget(mImageReader.getSurface());//设置拍照方向mCaptureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATION.get(rotation));//这个回调接口用于拍照结束时重启预览,因为拍照会导致预览停止CameraCaptureSession.CaptureCallback mImageSavedCallback = new CameraCaptureSession.CaptureCallback() {@Overridepublic void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {// Toast.makeText(getApplicationContext(), "Image Saved!", Toast.LENGTH_SHORT).show();//重启预览Log.e(TAG,"capture===>  restartPreview");restartPreview();}};//停止预览mCameraCaptureSession.stopRepeating();//开始拍照,然后回调上面的接口重启预览,因为mCaptureBuilder设置ImageReader作为target,所以会自动回调ImageReader的onImageAvailable()方法保存图片mCameraCaptureSession.capture(mCaptureBuilder.build(), mImageSavedCallback, null);Log.e(TAG,"capture===>  end");} catch (CameraAccessException e) {e.printStackTrace();}}private void restartPreview() {try {//执行setRepeatingRequest方法就行了,注意mCaptureRequest是之前开启预览设置的请求mCameraCaptureSession.setRepeatingRequest(mCaptureRequest, null, null);} catch (CameraAccessException e) {e.printStackTrace();}}private void setupImageReader() {//前三个参数分别是需要的尺寸和格式,最后一个参数代表每次最多获取几帧数据,本例的2代表ImageReader中最多可以获取两帧图像流mImageReader = ImageReader.newInstance(mCaptureSize.getWidth(), mCaptureSize.getHeight(), ImageFormat.JPEG, 2);//YUV_420_888//监听ImageReader的事件,当有图像流数据可用时会回调onImageAvailable方法,它的参数就是预览帧数据,可以对这帧数据进行处理mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {@Overridepublic void onImageAvailable(ImageReader reader) {Log.e(TAG,"========onImageAvailable==========");Image image = reader.acquireLatestImage();new Thread(new imageSaver(image,System.currentTimeMillis()+"")).start();}}, null);}public class imageSaver implements Runnable {private Image mImage;private String imgName;public imageSaver(Image image,String imgName) {mImage = image;this.imgName=imgName;}@Overridepublic void run() {//我们可以将这帧数据转成字节数组,类似于Camera1的PreviewCallback回调的预览帧数据ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();byte[] data = new byte[buffer.remaining()];buffer.get(data);File mImageFile = new File(Environment.getExternalStorageDirectory() + "/"+imgName+".jpg");FileOutputStream fos = null;try {fos = new FileOutputStream(mImageFile);fos.write(data, 0 ,data.length);} catch (IOException e) {e.printStackTrace();} finally {mImageFile = null;if (fos != null) {try {fos.close();fos = null;} catch (IOException e) {e.printStackTrace();}}mImage.close();}}}//选择sizeMap中大于并且最接近width和height的sizeprivate Size getOptimalSize(Size[] sizeMap,int Width,int height){ArrayList<Size> list=new ArrayList<>();Log.e(TAG,"Width="+Width+",height="+height);for(Size size:sizeMap){Log.e(TAG,"size.w="+size.getWidth()+"   size.h="+size.getHeight());if(size.getWidth()>Width && size.getHeight()>height) {list.add(new Size(size.getWidth(),size.getHeight()));Log.e(TAG,"===============list  size.w="+size.getWidth()+"   size.h="+size.getHeight());}}if(list.size()>0){Size size= Collections.min(list, new Comparator<Size>() {@Overridepublic int compare(Size o1, Size o2) {return o1.getWidth()*o1.getHeight() - o2.getWidth()*o2.getHeight();}});Log.e(TAG,"最终 size.w="+size.getWidth()+"  ,size.h="+size.getHeight());return size;}else{return sizeMap[0];}}
}

  

转载于:https://www.cnblogs.com/jtzp007/p/11605454.html

android 基础一 Camera2实现拍照功能相关推荐

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

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

  2. android 实现自动拍照,Android自定义相机实现定时拍照功能

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml andro ...

  3. android拍照功能编程,android实现手机App实现拍照功能示例

    实现手机App实现拍照功能结果如下 第一步: activity_takephoto.xml布局用SurfaceView xmlns:tools="http://schemas.android ...

  4. android调用系统相机实现拍照功能

    在实现拍照的功能时遇到了很多问题,搜索了很多资料,尝试了很多办法,终于解决了,下面简要的描述下在开发过程中遇到的问题. 虽然之前看过android开发的书,但是没有做过东西,这次也是临时决定让我做一个 ...

  5. android 自定义相机,Android自定义相机实现定时拍照功能

    这篇博客为大家介绍Android自定义相机,并且实现倒计时拍照功能. 首先自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件: activity_main.xml andro ...

  6. android studio操作手机相机,Android Studio 调用Camera实现拍照功能

    首先创建一个SurfaceHolder实现对SurfaceView的回调,然后重写SurfaceCreate函数,实现对Camera的初始化等一系列工作:代码如下: @Override public ...

  7. android基础学习之相机拍照部分

    在学习这个模块之前必须要对android有关于相机拍照的API有所了解  , 这个模块的API有两部分  一部分就是Camera 还有一部分 是Camera2 好像androidX包里面还有一个Cam ...

  8. Android 基础 —— 模拟实现拨打电话功能

    前面已经学习活动的显示跳转及隐式跳转,也学习 TextView 及 Button 两个控件的使用,下面我们来学习 EditText的使用: EditText 是程序用于和用户进行交互的另一个重要控件, ...

  9. Android如何使用Camera2拍照【简易快速上手篇】

    因为大部分的需求,并没有那么复杂,只需要简单的拍照功能,对于这种简单的需求,本文可以很好的满足.本文,是对Camera2做一个极简易的封装,以及去掉其它不重要的API,帮助你在几分钟内,使用Camer ...

最新文章

  1. 关系数据库的数据迁移
  2. python实现决策树算法sklearn_python sklearn-05:决策树及随机森林
  3. 蓝桥 BEGIN4 - Fibonacci数列
  4. BZOJ 4034: [HAOI2015]T2 树链剖分
  5. java 保存和读取本地文件
  6. c语言单向链表经典,C语言基础 - 实现单向链表
  7. 拿了股权的员工能不干活吗?
  8. 阿里云服务器对外开放tomcat端口访问
  9. Lua初学习 9-13_04 require moudle
  10. 蓝桥杯2016年第七届JavaC组国赛第一题-平方末尾
  11. 在MFC中通过opencv显示摄像头视频或者文件视频
  12. 大数据行业人士必知10大数据思维原理
  13. html中css鼠标手势样式,CSS鼠标手势
  14. 弘辽科技:直通车引流逻辑。
  15. 使用FFMpeg从mp4中提取mp3
  16. 计算机应用职业生涯规划,计算机应用技术职业规划书|计算机应用专业个人职业规划...
  17. 怎样清理xp系统垃圾
  18. C# 复数类 Complex
  19. teamviewer检测到商业用途的解决办法(win7 win8 win10亲测) 修改teamviewerID
  20. xp系统打印机没有服务器属性设置,xp系统打印机纸张设置的方法

热门文章

  1. XGB系列-XGB参数指南
  2. redis详细介绍附实例代码--看一篇就够了
  3. linux 开启SSH 22端口
  4. python数据处理基础 pandas dataframe
  5. 个人收款解决方案 V免签、Xpay
  6. 遍历文件夹下文件名 几种方法
  7. linux 中查看组成员命令,linux 用户和用户组命令
  8. Docker进阶篇 - (一)Docker Compose
  9. 关于使用docker启动容器失败解决访问
  10. 软件开发的模式及其优缺点