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) void OpenCamera Private () { the try { Log.e (the TAG, "OpenCamera"); CameraManager Manager = (CameraManager) the getSystemService (Context.CAMERA_SERVICE); the try { // iterate through all cameras for (String cameraId: manager.getCameraIdList () ) { CameraCharacteristics = manager.getCameraCharacteristics Characteristics (cameraId); // default open rear camera IF (characteristics.get (CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) continue; // Get StreamConfigurationMap, which is supported by all the management camera output formats and sizes StreamConfigurationMap characteristics.get Map = (CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); mPreviewSize = getOptimalSize (map.getOutputSizes (SurfaceTexture.class), mPreviewSize.getWidth (), mPreviewSize.getHeight ()); // get the camera supports a maximum shot size of the mCaptureSize = Collections.max (Arrays.asList (map.getOutputSizes (ImageFormat.JPEG)), new new Comparator <size> () { @Override public int the Compare (size lhs, RHS Size) { 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 mCaptureRequestBuilder = mCameraDevice.createCaptureRequest (CameraDevice.TEMPLATE_PREVIEW); public void onClosed(CameraDevice camera) { super.onClosed(camera); Log.e (TAG, "CameraState ==> OnClosed camera.id =" + camera.getId ()); // when calling CameraDevice.close () callback will turn off the camera equipment this method. Do not turn off the camera to camera equipment. // After the callback method is executed, any attempt to invoke the associated camera operation will fail and throw an IllegalStateException } } class CameraSessionState the extends CameraCaptureSession.StateCallback { @Override public void onConfigured (CameraCaptureSession the session) { Log.e (the TAG, "CameraSessionState onConfigured"); the try { // create CaptureRequestBuilder, TEMPLATE_PREVIEW ratio indicates the preview request // Surface set as the display screen of the preview data mCaptureRequestBuilder.addTarget (mSurfacePrevew); // create a capture request = mCaptureRequestBuilder.build mCaptureRequest (); mCameraCaptureSession = the session; // set the data acquisition request is repeated, so that the preview screen will always display the data mCameraCaptureSession.setRepeatingRequest (mCaptureRequest, null, null); } the catch (CameraAccessException E) { E. printStackTrace (); } } @Override public void onConfigureFailed (CameraCaptureSession the session) { Log.e (the TAG, "CameraSessionState onConfigureFailed"); } } class SurfaceTextureListener the 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; } // set the output to mImageReader CaptureRequest @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(); mCaptureBuilder.addTarget(mImageReader.getSurface()); // set the camera direction mCaptureBuilder.set (CaptureRequest.JPEG_ORIENTATION, ORIENTATION.get (rotation)); // this callback interface is used to restart at the end of the preview pictures, because pictures will cause a preview to stop CameraCaptureSession.CaptureCallback mImageSavedCallback = new new CameraCaptureSession.CaptureCallback () { @Override public onCaptureCompleted void (CameraCaptureSession the session, CaptureRequest Request, TotalCaptureResult Result) { // Toast.makeText (getApplicationContext (), "Image the Saved!", Toast.LENGTH_SHORT). Show (); // restart preview Log.e (TAG, "capture ===> restartPreview"); restartPreview (); } }; // stop the preview mCameraCaptureSession.stopRepeating (); // start taking pictures, and then restart the preview above callback interface because mCaptureBuilder set ImageReader as a target, it will automatically callback onImageAvailable ImageReader's () method to save the image mCameraCaptureSession .capture (mCaptureBuilder.build (), mImageSavedCallback, null); Log.e (the TAG, "Capture ===> End"); } the catch (CameraAccessException E) { e.printStackTrace (); } } Private void restartPreview () { the try { // perform setRepeatingRequest method on the line, before turning attention mCaptureRequest requests the preview is provided mCameraCaptureSession.setRepeatingRequest (mCaptureRequest, null, null); } the catch (CameraAccessException E) { e.printStackTrace (); } } Private void setupImageReader () { // the first three parameters are the desired size and form, the last parameter to get the most representative of each of several data frames, the present embodiment can be acquired ImageReader represents up to two image stream = ImageReader.newInstance mImageReader (mCaptureSize.getWidth (), mCaptureSize.getHeight (), ImageFormat.JPEG, 2); // YUV_420_888 // ImageReader event listener, when the image data stream will be available onImageAvailable callback method, its parameters is a preview frame data, the frame data can be processed on this mImageReader.setOnImageAvailableListener (new new ImageReader.OnImageAvailableListener () { @Override public void onImageAvailable (the ImageReader Reader) { Log.e (the TAG, "======== onImageAvailable = ========= "); public class imageSaver the implements the Runnable { Private Image mImage; Image Image reader.acquireLatestImage = (); the Thread new new (new new imageSaver (Image, System.currentTimeMillis () + "")) Start ();. } }, null); } buffer.get (Data); imgName String Private; public imageSaver (Image Image, String imgName) { mImage = Image; this.imgName = imgName; } @Override public void RUN () { // we frame these data into a byte array, similar Camera1 preview frames of data callback PreviewCallback the ByteBuffer mImage.getPlanes Buffer = () [0] .getBuffer (); byte [] = new new data byte [buffer.remaining ()]; File = mImageFile new new File (Environment.getExternalStorageDirectory () + "/"+imgName+".jpg"); a FileOutputStream fos = null; the try { fos = new new a 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]; } } }