在Android平台上,调用摄像头是开发移动应用时常见的功能,主要涉及到系统提供的Camera API或CameraX库。本文将深入探讨如何在Android应用中实现摄像头调用,并将拍照结果保存到SD卡的根目录。
我们需要了解Android的相机权限。在AndroidManifest.xml文件中,必须声明``来获取访问相机的权限,如:
```xml
```
同时,如果要将图片保存到外部存储(如SD卡),还需声明`WRITE_EXTERNAL_STORAGE`权限,对于Android 6.0及以上版本,还需要在运行时动态请求权限。
接下来,我们讨论如何使用Camera API。Android SDK提供了Camera类,允许开发者直接控制摄像头。以下是一个简单的相机启动示例:
```java
// 获取默认的相机ID
int cameraId = Camera.getNumberOfCameras() - 1; // 假设最后一个为后置摄像头
Camera.open(cameraId); // 打开指定的相机
// 设置预览显示视图
CameraPreview preview = (CameraPreview) findViewById(R.id.camera_preview);
Camera.setPreviewDisplay(preview.getHolder());
// 开始预览
Camera.startPreview();
```
`CameraPreview`是一个自定义的SurfaceView,用于显示摄像头预览画面。当用户点击拍照按钮时,可以调用`takePicture()`方法进行拍照:
```java
Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// 处理拍照后的图片数据
File pictureFile = createImageFile(); // 创建图片文件
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
// 释放相机资源
camera.release();
}
};
// 触发拍照
camera.takePicture(null, null, pictureCallback);
```
`createImageFile()`函数用于在SD卡根目录创建一个图片文件:
```java
private File getExternalFilesDir(String type) {
return Environment.getExternalStoragePublicDirectory(type);
}
private File createImageFile() throws IOException {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timestamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
return image;
}
```
然而,Camera API比较复杂且难以使用,Google在Android X库中推出了CameraX,这是一个现代、易于使用的相机框架。使用CameraX,你可以更简洁地实现相同的功能:
```kotlin
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder()
.build()
.also { it.setSurfaceProvider(binding.previewView.surfaceProvider) }
val imageCapture = ImageCapture.Builder()
.setTargetRotation(windowManager.defaultDisplay.rotation)
.build()
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview, imageCapture)
val takePictureButton = findViewById
1