如何调用设备摄像头进行拍照、预览并将拍摄结果保存在媒体库中(Camera)("手机拍照全攻略:调用摄像头拍照、实时预览及保存照片到媒体库")

原创
ithorizon 4周前 (10-19) 阅读数 21 #后端开发

手机拍照全攻略:调用摄像头拍照、实时预览及保存照片到媒体库

一、引言

在移动应用开发中,调用设备摄像头进行拍照和预览是一个常见的需求。本文将详细介绍怎样在Android和iOS平台上使用原生API调用摄像头进行拍照、实时预览以及将拍摄最终保存在媒体库中。我们将涵盖从摄像头权限申请、摄像头配置、拍照、预览到保存照片的完整流程。

二、摄像头权限申请

在调用摄像头之前,首先需要申请相应的权限。以下是Android和iOS平台上申请摄像头权限的代码示例。

Android平台权限申请

// 在AndroidManifest.xml中添加以下权限

// 在代码中动态申请权限

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)

!= PackageManager.PERMISSION_GRANTED) {

ActivityCompat.requestPermissions(this,

new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},

MY_CAMERA_REQUEST_CODE);

}

iOS平台权限申请

// 在Info.plist中添加以下权限

NSCameraUsageDescription

NSPhotoLibraryUsageDescription

// 在代码中动态申请权限

AVAuthorizationStatus cameraAuthorizationStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

if (cameraAuthorizationStatus == AVAuthorizationStatusNotDetermined) {

[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {

if (granted) {

// 权限被授予

} else {

// 权限被拒绝

}

}];

}

三、摄像头配置与预览

在申请到权限后,接下来需要配置摄像头并进行预览。以下是Android和iOS平台上摄像头配置和预览的代码示例。

Android平台摄像头配置与预览

// 创建Camera对象

Camera camera = Camera.open();

// 配置摄像头参数

Camera.Parameters parameters = camera.getParameters();

parameters.setPreviewSize(640, 480);

parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);

camera.setParameters(parameters);

// 设置摄像头预览的SurfaceView

SurfaceView surfaceView = findViewById(R.id.camera_preview);

SurfaceHolder surfaceHolder = surfaceView.getHolder();

surfaceHolder.addCallback(new SurfaceHolder.Callback() {

@Override

public void surfaceCreated(SurfaceHolder holder) {

try {

camera.setPreviewDisplay(holder);

camera.startPreview();

} catch (IOException e) {

e.printStackTrace();

}

}

@Override

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

// 如果预览可以更改或旋转,请在此处处理这些事件。确保重新开端预览。

if (surfaceHolder.getSurface() == null) {

return;

}

try {

camera.stopPreview();

} catch (Exception e) {

// 忽略:尝试停止不存在的预览

}

try {

camera.setPreviewDisplay(holder);

camera.startPreview();

} catch (Exception e) {

e.printStackTrace();

}

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

// 清理和释放资源

camera.stopPreview();

camera.release();

camera = null;

}

});

iOS平台摄像头配置与预览

// 创建AVCaptureSession对象

AVCaptureSession *session = [[AVCaptureSession alloc] init];

// 选择摄像头

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

// 创建 AVCaptureDeviceInput 对象并添加到会话中

AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];

if ([session canAddInput:input]) {

[session addInput:input];

} else {

// 处理差错

}

// 创建 AVCaptureVideoPreviewLayer 对象并添加到视图

AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session];

previewLayer.frame = self.view.bounds;

[self.view.layer addSublayer:previewLayer];

// 开端预览

[session startRunning];

四、拍照

在摄像头预览正常后,接下来我们将实现拍照功能。以下是Android和iOS平台上拍照的代码示例。

Android平台拍照

// 拍照的回调方法

Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {

@Override

public void onPictureTaken(byte[] data, Camera camera) {

// 保存照片到媒体库

File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);

if (pictureFile == null) {

return;

}

try {

FileOutputStream fos = new FileOutputStream(pictureFile);

fos.write(data);

fos.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

// 通知媒体库更新

MediaScannerConnection.scanFile(context, new String[]{pictureFile.toString()}, null, null);

}

};

// 拍照

camera.takePicture(null, null, pictureCallback);

iOS平台拍照

// 创建 AVCapturePhotoOutput 对象并添加到会话中

AVCapturePhotoOutput *photoOutput = [[AVCapturePhotoOutput alloc] init];

if ([session canAddOutput:photoOutput]) {

[session addOutput:photoOutput];

} else {

// 处理差错

}

// 拍照

[photoOutput capturePhotoWithSettings:[AVCapturePhotoSettings new]

delegate:self];

五、保存照片到媒体库

在拍照完成后,我们需要将照片保存到媒体库中,以便用户可以在相册中查看。以下是Android和iOS平台上保存照片到媒体库的代码示例。

Android平台保存照片到媒体库

private static File getOutputMediaFile(int type) {

// 确保外部存储可用

if (!isExternalStorageAvailable()) {

return null;

}

// 创建媒体存储目录

File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(

Environment.DIRECTORY_PICTURES), "MyApp");

// 创建一个以当前时间戳命名的媒体文件

String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

File mediaFile;

if (type == MEDIA_TYPE_IMAGE) {

mediaFile = new File(mediaStorageDir.getPath() + File.separator +

"IMG_" + timeStamp + ".jpg");

} else {

return null;

}

return mediaFile;

}

private static boolean isExternalStorageAvailable() {

String state = Environment.getExternalStorageState();

return Environment.MEDIA_MOUNTED.equals(state);

}

iOS平台保存照片到媒体库

// 拍照完成的回调方法

- (void)captureOutput:(AVCapturePhotoOutput *)output didFinishProcessingPhotoSampleBuffer:(CMSampleBufferRef)sampleBuffer previewPhotoSampleBuffer:(CMSampleBufferRef *)previewPhotoSampleBuffer resolvedSettings:(AVCaptureResolvedPhotoSettings *)resolvedSettings bracketSettings:(AVCaptureBracketedStillImageSettings *)bracketSettings error:(NSError *)error {

// 从sampleBuffer中获取图片数据

NSData *imageData = [AVCapturePhotoOutput AVCapturePhotoOutputCopyImageData sampleBuffer:sampleBuffer];

// 将图片数据变成UIImage

UIImage *image = [[UIImage alloc] initWithData:imageData scale:1.0 orientation:UIImageOrientationUp];

// 保存图片到媒体库

if ([UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:], NULL)]) {

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"保存胜利" message:@"照片已保存到相册" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];

[alertView show];

} else {

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"保存落败" message:@"照片未能保存到相册" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];

[alertView show];

}

}

// 图片保存完成的回调方法

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {

if (error == nil) {

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"保存胜利" message:@"照片已保存到相册" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];

[alertView show];

} else {

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"保存落败" message:@"照片未能保存到相册" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];

[alertView show];

}

}

六、总结

本文详细介绍了在Android和iOS平台上调用摄像头进行拍照、实时预览以及将拍摄最终保存在媒体库中的完整流程。通过掌握这些技术,开发者可以轻松实现移动应用中的拍照功能,并提供更好的用户体验。需要注意的是,摄像头API大概会随着操作系统版本的更新而出现变化,由此开发者需要关注官方文档,确保代码的兼容性。


本文由IT视界版权所有,禁止未经同意的情况下转发

文章标签: 后端开发


热门