public class SurfaceViewActivity extends AppCompatActivity { String TAG="SurfaceViewActivity_AA"; TextureView textureView=null; CaptureRequest.Builder mCaptureRequestBuilder; CaptureRequest mCaptureRequest; Surface mSurfacePrevew; //预览的surface ImageReader 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); } @Override protected 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() { @Override public 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>() { @Override public 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 { @Override public void onOpened(CameraDevice camera) { mCameraDevice = camera; try { setupImageReader(); SurfaceTexture mSurfaceTexture = textureView.getSurfaceTexture(); //设置TextureView的缓冲区大小 mSurfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); //获取Surface显示预览数据 mSurfacePrevew = new Surface(mSurfaceTexture); //需要同时增加预览和拍照的 Surface camera.createCaptureSession(Arrays.asList(mSurfacePrevew,mImageReader.getSurface()), new CameraSessionState(), null); }catch (Exception ex){} } @Override public void onDisconnected(CameraDevice camera) { Log.e(TAG,"CameraState ==> onDisconnected camera.id="+camera.getId()); } @Override public void onError(CameraDevice camera, int error) { Log.e(TAG,"CameraState ==> handleMessage camera.id="+camera.getId()+" error="+error); } @Override public 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{ @Override public 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(); } } @Override public void onConfigureFailed(CameraCaptureSession session) { Log.e(TAG,"CameraSessionState onConfigureFailed"); } } class SurfaceTextureListener implements TextureView.SurfaceTextureListener{ @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { Log.e(TAG,"SurfaceTextureListener===> onSurfaceTextureAvailable"); mPreviewSize=new Size(width,height); OpenCamera(); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { Log.e(TAG,"SurfaceTextureListener===> onSurfaceTextureSizeChanged"); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { Log.e(TAG,"SurfaceTextureListener===> onSurfaceTextureDestroyed"); return false; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { // Log.e(TAG,"SurfaceTextureListener===> onSurfaceTextureUpdated"); } } private void capture() { Log.e(TAG,"capture===> "); try { //首先我们创建请求拍照的CaptureRequest if(mCameraDevice==null) return; final CaptureRequest.Builder mCaptureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); //获取屏幕方向 int rotation = getWindowManager().getDefaultDisplay().getRotation(); //设置CaptureRequest输出到mImageReader mCaptureBuilder.addTarget(mImageReader.getSurface()); //设置拍照方向 mCaptureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATION.get(rotation)); //这个回调接口用于拍照结束时重启预览,因为拍照会导致预览停止 CameraCaptureSession.CaptureCallback mImageSavedCallback = new CameraCaptureSession.CaptureCallback() { @Override public 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() { @Override public 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; } @Override public 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的size private 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>() { @Override public 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]; } } }