CameraX实际上还是用的Camera2的代码,但是它对调用API进行了很好的封装,使用起来对比直接Camera2更加的方便。同时使用需要绑定lifecircle,能够自动管理生命周期。
添加依赖
1 2 3 4 implementation "androidx.camera:camera-core:1.0.0-rc01" implementation "androidx.camera:camera-camera2:1.0.0-rc01" implementation 'androidx.camera:camera-view:1.0.0-alpha20' implementation "androidx.camera:camera-lifecycle:1.0.0-rc01"
申请权限
1 <uses-permission android:name="android.permission.CAMERA" />
1 2 3 4 int checkCallPhonePermission = ContextCompat.checkSelfPermission(this , Manifest.permission.CAMERA);if (checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this , new String[]{Manifest.permission.CAMERA}, 222 ); }
预览
1 2 3 4 <androidx.camera.view.PreviewView android:id="@+id/tv_camera" android:layout_width="match_parent" android:layout_height="match_parent" />
cameraX显示布局需要PreviewView,直接在xml中添加。
启动相机,需要先获取到ProcessCameraProvider:
1 2 3 4 5 6 previewView.post(new Runnable() { @Override public void run () { setupCamera(); } });
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void setupCamera () { ListenableFuture<ProcessCameraProvider> instance = ProcessCameraProvider.getInstance(this ); instance.addListener(new Runnable() { @Override public void run () { try { cameraProvider = instance.get(); } catch (ExecutionException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } if (cameraProvider != null ) { startCamera(); } } }, ContextCompat.getMainExecutor(this )); }
添加预览的参数preview:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private void startCamera () { Preview preview = new Preview.Builder() .setTargetAspectRatio(AspectRatio.RATIO_16_9) .setTargetRotation(Surface.ROTATION_90) .build(); ImageCapture imageCapture = new ImageCapture.Builder() .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY) .setTargetAspectRatio(AspectRatio.RATIO_16_9) .setTargetRotation(Surface.ROTATION_90) .build(); ImageAnalysis imageAnalysis = new ImageAnalysis.Builder().setTargetAspectRatio(AspectRatio.RATIO_16_9).setTargetRotation(Surface.ROTATION_90).build(); imageAnalysis.setAnalyzer(cameraExecutor, new ImageAnalysis.Analyzer() { @Override public void analyze (@NonNull ImageProxy image) { Log.e("画面" , image.getWidth() + "**" + image.getHeight()); } }); CameraSelector selector = new C ameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build(); cameraProvider.unbindAll(); cameraProvider.bindToLifecycle(this , selector, preview, imageCapture, imageAnalysis); preview.setSurfaceProvider(previewView.getSurfaceProvider()); }
bindToLifecycle方法中的preview、imageCapture和imageAnalysis并不是每次都需要,如果只是预览的话就只传preview即可。
图像分析
ImageAnalysis
可以帮助我们做一些图像质量的分析,需要我们去实现 ImageAnalysis.Analyzer
接口的 analyze
方法。
拍照
拍照需要在预览的基础上,调用ImageCapture拍照,同时需要创建OutputFileOptions用以存储文件信息。在onImageSaved方法回调时,照片会自动存储到对应的文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public void takePicture (View v) { imageCapture.setFlashMode(ImageCapture.FLASH_MODE_AUTO); File file = new File(getCacheDir()+"/" +System.currentTimeMillis()+".png" ); if (!file.exists()){ try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build(); imageCapture.takePicture(outputFileOptions, cameraExecutor, new ImageCapture.OnImageSavedCallback() { @Override public void onImageSaved (@NonNull ImageCapture.OutputFileResults outputFileResults) { if (outputFileResults.getSavedUri() != null ) { } } @Override public void onError (@NonNull ImageCaptureException exception) { } }); }
录像
录像是需要创建VideoCapture,同时在bind方法中不能和imageAnalysis一起使用。
1 2 3 4 5 6 7 8 9 10 11 videoCapture = new VideoCapture.Builder() .setTargetRotation(Surface.ROTATION_0) .setTargetAspectRatio(AspectRatio.RATIO_16_9) .setAudioBitRate(44100 ) .setAudioRecordSource(MediaRecorder.AudioSource.MIC) .setVideoFrameRate(25 ) .setBitRate(3 * 1024 * 1024 ) .build();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 if (start) { videoCapture.stopRecording(); start = false ; } else { File file = new File(Environment.getExternalStorageDirectory() + "/" + System.currentTimeMillis() + ".mp4" ); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } VideoCapture.OutputFileOptions outputFileOptions = new VideoCapture.OutputFileOptions.Builder(file).build(); videoCapture.startRecording(outputFileOptions, cameraExecutor, new VideoCapture.OnVideoSavedCallback() { @Override public void onVideoSaved (@NonNull VideoCapture.OutputFileResults outputFileResults) { Log.e("画面" , "视频保存成功" ); } @Override public void onError (int videoCaptureError, @NonNull String message, @Nullable Throwable cause) { } }); start = true ; }
CameraView
如果觉得上面的代码还是比较多,官方提供了一个极简拍摄的组件CameraView。
在xml中添加依赖:
1 2 3 4 5 <androidx.camera.view.CameraView android:id ="@+id/view_finder" android:layout_width ="match_parent" android:layout_height ="match_parent" />
同时通过绑定开始预览,并调用对应的takePicture和startRecording,完成拍照和摄影,这两个方法的参数与上面相同。
1 2 3 4 cameraView = findViewById(R.id.view_finder); cameraView.bindToLifecycle(this ); cameraView.takePicture(...); cameraView.startRecording(...);
CameraX官方还未出正式版本,这部分的代码各个版本改动较大,建议直接参考官方demo:https://github.com/android/camera-samples/tree/main/CameraXBasic