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.遇到的一些问题
拍照的原理我能搞懂,并且可以进行拍照,但我不知道怎么把拍出来的照片弄到自己手机的相册里面,我先自己再弄一下,下篇博客再解决这个问题。
Comments | NOTHING