CameraX是谷歌提供的一个JetPack,它首先比Camera1,Camera2要好,但好在哪里我现在还不知道。它提供了拍照,录像,预览等功能

现在看怎么调用:

1.build里面的东西

// CameraX核心库
implementation 'androidx.camera:camera-core:1.1.0-beta01'

// CameraX Camera2扩展库
implementation 'androidx.camera:camera-camera2:1.1.0-beta01'

// CameraX生命周期库
implementation 'androidx.camera:camera-lifecycle:1.1.0-beta01'

// CameraX View扩展库
implementation 'androidx.camera:camera-view:1.0.0-alpha27'

2.获取权限

<uses-permission android:name="android.permission.CAMERA" />
   获取camera的权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
   获取存储权限

但是就这样还是不能调用,因为这是一个危险权限,需要手动调用

手动调用

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED ||
      ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
  // 如果没有这两个权限,请请求用户授权
  ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 2);
}

回调函数

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
   super.onRequestPermissionsResult(requestCode, permissions, grantResults);
   if(requestCode==2){
       if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED &&
               grantResults[1] == PackageManager.PERMISSION_GRANTED) {
           // 用户已授予相机和存储权限
           startCamera();
      } else {
           // 用户拒绝授予相机和存储权限
           Toast.makeText(this,"没有授予权限",Toast.LENGTH_SHORT).show();
      }
  }
}

但是嘛,这个回调函数在activity里面没问题,但是在fragment里面就调用不了,应该已经被舍弃了。


3.调用Camera

//是用来获取 ProcessCameraProvider 实例的方法,
// ProcessCameraProvider 是一个用于管理相机的类,可以使用它来创建 Camera 对象,
// 实现预览、拍照、录制视频等功能。
//所以cameraProviderFuture是一个集合类型的
ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);

cameraProviderFuture.addListener(() -> {

try {
   // 获取CameraProvider
 ProcessCameraProvider cameraProvider = cameraProviderFuture.get();

 // 选择相机
  CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
               
   
  // 配置预览
  Preview preview = new Preview.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3).
//                       setTargetRotation(mPreviewView.getDisplay().getRotation())
                       build();

               // 绑定预览到PreviewView
  preview.setSurfaceProvider(mPreviewView.getSurfaceProvider());
// 配置图像捕获
   ImageCapture imageCapture = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.setTargetAspectRatio(AspectRatio.RATIO_16_9)
                       // setTargetRotation(mPreviewView.getDisplay().getRotation()),弄方向的
.build();
   
// 绑定用例到相机
cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview, imageCapture);

   // 设置拍照按钮的点击事件
   mButton.setOnClickListener(view -> {
                   // 创建文件以保存图像
                    File storageDir =    Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
                    // 创建一个子目录
                    File outputDirectory = new File(storageDir, "MyApp");
                    // 如果目录不存在,则创建它
                    if (!outputDirectory.exists()) {
                        outputDirectory.mkdirs();
                    }
                    File photoFile = new File(outputDirectory, "photo.jpg");

// 创建一个保存照片的输出配置
                    ImageCapture.OutputFileOptions outputOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build();

// 拍照
  imageCapture.takePicture(outputOptions, ContextCompat.getMainExecutor(getContext()), new ImageCapture.OnImageSavedCallback() {
                        @Override
                        public void onImageSaved(@NonNull ImageCapture.OutputFileResults output) {
                            // 照片已保存到本地相册
                            Uri savedUri = output.getSavedUri() != null ? output.getSavedUri() : Uri.fromFile(photoFile);
                            Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                            mediaScanIntent.setData(savedUri);
                            getContext().sendBroadcast(mediaScanIntent);
                            Toast.makeText(getContext(),"拍照成功",Toast.LENGTH_SHORT).show();
                        }

                        @Override
                        public void onError(@NonNull ImageCaptureException exception) {
                            // 处理错误
                            Toast.makeText(getContext(),"失败",Toast.LENGTH_SHORT).show();
                        }
                    });
              });

          } catch (ExecutionException | InterruptedException e) {
               // 处理异常
               e.printStackTrace();
          }
      }, ContextCompat.getMainExecutor(getContext()));

写一下思路,

ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(this);
//是用来获取 ProcessCameraProvider 实例的方法,
// ProcessCameraProvider 是一个用于管理相机的类,可以使用它来创建 Camera 对象,
// 实现预览、拍照、录制视频等功能。
//所以cameraProviderFuture是一个集合类型的



cameraProviderFuture.addListener()
//cameraProviderFuture.addListener() 是 Android CameraX 库中的一个方法,它注册一个监听器,以便在代表相机提供程序可用性的 ListenableFuture 可用时通知该监听器。
//当相机提供程序可用时,监听器的 onSuccess 方法会被调用,并传递 CameraProvider 对象作为参数。
   
   
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
// 获取CameraProvider


CameraSelector cameraSelector = new CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK).build();
// 选择相机


 // 配置预览
Preview preview = new Preview.Builder().setTargetAspectRatio(AspectRatio.RATIO_4_3).
//                       setTargetRotation(mPreviewView.getDisplay().getRotation())
 build();
//选择4:3的预览视图,你可以选择4:3,也可以选择16:9的


preview.setSurfaceProvider(mPreviewView.getSurfaceProvider());
//绑定视图,mPreviewView是xml界面的PreviewView里面的,mPreviewView是把它实例化。之后把4:3的那个视图绑定在这个mPreviewView里面。

ImageCapture imageCapture = new ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)//最小化延迟
.setTargetAspectRatio(AspectRatio.RATIO_16_9)//目标宽高比16:9
                       // setTargetRotation(mPreviewView.getDisplay().getRotation()),弄方向的
.build();

//这段代码是在使用 Android CameraX 库中的 ImageCapture API 来创建一个用于捕获图像的实例。
//具体来说,这个实例使用了 ImageCapture.Builder() 方法创建,通过设置不同的参数来控制图像的捕获方式。在这里,它设置了捕获模式为最小化延迟,目标宽高比为16:9,并可以设置图像捕获时的旋转方向,以确保图像方向正确。
//一旦创建了 ImageCapture 实例,就可以使用它来捕获图像。


cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview, imageCapture);
// 绑定用例到相机

先以这块为一个分水岭:

先获取ProcessCameraProvider 实例的方法

然后注册一个监听器,以便在代表相机提供程序可用性的 ListenableFuture 可用时通知该监听器,

获取CameraProvider,然后选择相机(其中设置到底选择前置相机还是后置相机)

再配置预览(你的预览图是4:3,还是16:9)

将这个预览图和你自己xml里面的预览图绑定

创建了 ImageCapture 实例,就可以使用它来捕获图像(例如设置目标宽高比,延迟选大的还是小的)

最后把这个ImageCapture绑定到CameraProvider上,最后进行拍照。


4.遇到的一些问题

拍照的原理我能搞懂,并且可以进行拍照,但我不知道怎么把拍出来的照片弄到自己手机的相册里面,我先自己再弄一下,下篇博客再解决这个问题。


一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。