Android:Camera API 学习(二)
一、Android:保存媒体文件
用户创建的照片和视频等媒体文件应保存到设备的外部存储目录(SD 卡)中,这样不仅可以节省系统空间,还能让用户在不使用其设备的情况下访问这些文件。您可以将媒体文件保存至设备上的多个目录位置,但作为开发者,您应考虑的标准位置仅有两个:
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) 此方法会返回一个标准的共享位置(推荐位置),用于保存照片和视频。此目录为共享(公开)目录,因此其他应用可轻松发现、读取、更改和删除保存在此位置中的文件。如果用户卸载了您的应用,保存到此位置的媒体文件将不会遭到移除。为避免干扰用户的现有照片和视频,您应该在此目录中创建一个子目录,用于保存您应用的媒体文件。Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) 此方法会返回一个标准位置,用于保存与您的应用相关联的照片和视频。如果用户卸载了您的应用,保存在此位置中的所有文件都将遭到移除。系统没有对此位置中的文件采取任何强制的安全措施,因此其他应用可以读取、更改和删除它们。
以下示例代码演示了如何为媒体文件创建 File 或 Uri 位置,以便在使用 Intent 调用设备相机时或在构建相机应用的过程中使用。
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
private static Uri getOutputMediaFileUri(int type){
return Uri.fromFile(getOutputMediaFile(type));
}
private static File getOutputMediaFile(int type){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyCameraApp");
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
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 if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
注意:Environment.getExternalStoragePublicDirectory() 在 Android 2.2(API 级别 8) 或更高版本中可用。如果您的目标设备搭载的是较低版本的 Android 系统,请改用 Environment.getExternalStorageDirectory()。
二、相机功能
Android 支持多种相机功能(例如,照片格式、闪光灯模式、对焦设置等),您可以使用相机应用控制这些功能。本部分列出了一些常用的相机功能,并简要讨论了如何使用它们。您可以使用 Camera.Parameters 对象访问和设置大多数相机功能。但有几项重要功能需要的不仅仅是在 Camera.Parameters 中进行简单设置。
1.检查功能可用性
开始着手在 Android 设备上使用相机功能时,首先要明白的是,并非所有设备都支持所有的相机功能。此外,支持特定功能的设备对这些功能提供的支持级别可能有所不同,或者可能提供不同的支持选项。因此,在开发相机应用时,您需要决定要支持的相机功能以及所提供的支持级别,这是决策过程的一部分。做出该决策后,您应计划在相机应用中添加相应代码,用于检查设备硬件是否支持这些功能,以及能否在功能不可用时安全地退出。
您可以通过以下方式检查相机功能的可用性:获取相机参数对象实例,并检查相关方法。以下代码示例展示了如何获取 Camera.Parameters 对象并检查相机是否支持自动对焦功能:
Camera.Parameters params = camera.getParameters();
List<String> focusModes = params.getSupportedFocusModes();
if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
}
您可以使用上述方法检查大多数相机功能。Camera.Parameters 对象提供 getSupported...()、is...Supported() 或 getMax...() 方法,用于确定是否支持(以及在多大程度上支持)某项功能。
如果您的应用需要某些相机功能才能正常运行,您可以通过将这些功能添加到应用清单中进行请求。当您声明需要使用特定相机功能(例如闪光灯和自动对焦)时,Google Play 会阻止将您的应用安装在不支持这些功能的设备上。
2.使用相机功能
您可以使用 Camera.Parameters 对象启用和控制大多数相机功能。如需获取该对象,首先要获取 Camera 对象实例,调用 getParameters() 方法,更改返回的参数对象,然后将其设置回相机对象,如以下示例代码所示:
Camera.Parameters params = camera.getParameters();
params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
camera.setParameters(params);
此方法适用于几乎所有的相机功能,并且在获取 Camera 对象实例后,您可以随时更改大部分参数。对参数进行更改后,用户通常能够立即在应用的相机预览中看到相关更改。在软件方面,参数更改可能需要经过几个帧才能真正生效,因为相机硬件需要先处理新指令,然后才会发送更新后的图片数据。
重要提示:某些相机功能无法随意更改。具体来说,在更改相机预览的大小或屏幕方向时,首先需要停止预览,更改预览大小,然后再重启预览。从 Android 4.0(API 级别 14) 开始,更改预览屏幕方向无需重启预览。
其他需要更多代码才能实现的相机功能包括:
3.区域测光和对焦
在某些拍摄场景中,自动对焦和测光可能无法产生理想的效果。从 Android 4.0(API 级别 14) 开始,您的相机应用可以提供更多控件,让您的应用或用户能够在图片中指定用于确定对焦或亮度等级设置的区域,并将这些值传递给相机硬件,用于拍摄图片或视频。
区域测光和对焦的工作原理与其他相机功能非常类似,因为您可以通过 Camera.Parameters 对象中的方法控制它们。以下代码演示了如何为一个 Camera 实例设置两个测光区域:
camera = getCameraInstance();
Camera.Parameters params = camera.getParameters();
if (params.getMaxNumMeteringAreas() > 0){
List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
Rect areaRect1 = new Rect(-100, -100, 100, 100);
meteringAreas.add(new Camera.Area(areaRect1, 600));
Rect areaRect2 = new Rect(800, -1000, 1000, -800);
meteringAreas.add(new Camera.Area(areaRect2, 400));
params.setMeteringAreas(meteringAreas);
}
camera.setParameters(params);
Camera.Area 对象包含两个数据参数:一个 Rect 对象(用于指定相机视野范围内的区域)和一个 weight 值(用于告知相机在计算测光或对焦时应为此区域指定的重要性级别)。
4.人脸检测
对于包含人物的照片,人脸通常是照片中最重要的部分,在拍摄图片时,应使用人脸确定焦点和白平衡。Android 4.0(API 级别 14) 框架提供了一系列 API,可利用人脸识别技术识别人脸并计算照片设置值。
注意:当人脸检测功能处于启用状态时,setWhiteBalance(String)、setFocusAreas(List<Camera.Area>) 和 setMeteringAreas(List<Camera.Area>) 不起任何作用。
在相机应用中使用人脸检测功能时,需要执行若干个一般步骤:
- 检查设备是否支持人脸检测
- 创建人脸检测监听器
- 将人脸检测监听器添加到相机对象
- 在预览(以及每次重启预览)后启用人脸检测
并非所有设备都支持人脸检测功能。您可通过调用 getMaxNumDetectedFaces() 检查设备是否支持该功能。以下 startFaceDetection() 示例方法展示了如何执行这项检查。
为了在检测到人脸时收到通知并做出响应,您的相机应用必须为人脸检测事件设置监听器。为此,您必须创建一个可实现 Camera.FaceDetectionListener 接口的监听器类,如以下示例代码所示。
class MyFaceDetectionListener implements Camera.FaceDetectionListener {
@Override
public void onFaceDetection(Face[] faces, Camera camera) {
if (faces.length > 0){
Log.d("FaceDetection", "face detected: "+ faces.length +
" Face 1 Location X: " + faces[0].rect.centerX() +
"Y: " + faces[0].rect.centerY() );
}
}
}
创建此类后,在应用的 Camera 对象中设置此类,如以下示例代码所示:
camera.setFaceDetectionListener(new MyFaceDetectionListener());
每当您启动(或重启)相机预览时,您的应用都必须启用人脸检测功能。创建一个用于启用人脸检测的方法,这样您就可以根据需要调用该方法,如以下示例代码所示。
public void startFaceDetection(){
Camera.Parameters params = mCamera.getParameters();
if (params.getMaxNumDetectedFaces() > 0){
mCamera.startFaceDetection();
}
}
每次启动(或重启)相机预览时,必须启用人脸检测。如果您使用的是创建预览类部分中的预览类,请将 startFaceDetection() 方法添加到该预览类中的 surfaceCreated() 和 surfaceChanged() 方法中,如以下示例代码所示。
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
startFaceDetection();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
if (holder.getSurface() == null){
Log.d(TAG, "holder.getSurface() == null");
return;
}
try {
mCamera.stopPreview();
} catch (Exception e){
Log.d(TAG, "Error stopping camera preview: " + e.getMessage());
}
try {
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
startFaceDetection();
} catch (Exception e){
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
注意:请记得先调用 startPreview() ,然后再调用此方法。请勿试图在相机应用主 Activity 的 onCreate() 方法中启用人脸检测,因为此时预览在应用的执行过程中尚不可用。
5.延时摄影视频
借助延时摄影视频功能,用户可以将间隔几秒钟或几分钟拍摄的照片串联起来,创建视频剪辑。此功能使用 MediaRecorder 以延时摄影顺序录制图片。
如需使用 MediaRecorder 录制延时摄影视频,您必须像录制常规视频一样配置录制器对象,将每秒捕获的帧数设置成较小的数值并使用一个延时摄影质量设置,如以下代码示例所示。
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH));
...
mediaRecorder.setCaptureRate(0.1);
6.需要权限的相机字段
在 Android 10(API 级别 29) 或更高版本的上运行的应用必须具有 CAMERA 权限,才能访问 getCameraCharacteristics() 方法返回的以下字段的值:
LENS_POSE_ROTATION LENS_POSE_TRANSLATION LENS_INTRINSIC_CALIBRATION LENS_RADIAL_DISTORTION LENS_POSE_REFERENCE LENS_DISTORTION LENS_INFO_HYPERFOCAL_DISTANCE LENS_INFO_MINIMUM_FOCUS_DISTANCE SENSOR_REFERENCE_ILLUMINANT1 SENSOR_REFERENCE_ILLUMINANT2 SENSOR_CALIBRATION_TRANSFORM1 SENSOR_CALIBRATION_TRANSFORM2 SENSOR_COLOR_TRANSFORM1 SENSOR_COLOR_TRANSFORM2 SENSOR_FORWARD_MATRIX1 SENSOR_FORWARD_MATRIX2
end
时间:2022/03/03
参考:https://developer.android.google.cn/guide/topics/media/camera#face-detection
|