Camera1 API详解

Posted Mr.Biandan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Camera1 API详解相关的知识,希望对你有一定的参考价值。

以下内容完全参考android官方文档

Android 框架包含对各种相机和设备上可用相机功能的支持,使您能够在应用中捕获照片和视频。本文档将介绍一种捕获图像和视频的简单快捷方法,还会概述一种为用户打造自定义相机体验的高级方法。

注意:本页面所描述的 Camera 类已弃用。我们建议您使用更新的 camera2 类,后者能在 Android 5.0(API 级别 21)或更高版本上运行。请通过我们的博客了解关于 camera2 的更多信息,并观看此视频。

请参阅下列相关资源:
* MediaPlayer 概览
* 数据和文件存储概览

注意事项
在让您的应用可以在 Android 设备上使用相机之前,您应该考虑关于您的应用打算如何使用此硬件功能的一些问题。

* 相机要求 - 使用相机是否对于您的应用非常重要,以至于您不想让应用安装在没有相机的设备上?如果是,则您应在清单文件中声明相机需求。
* 快照或自定义相机 - 您的应用将如何使用相机?您是否只是对拍摄快照或视频剪辑感兴趣,抑或是您的应用会提供一种使用相机的新方法?如果要拍摄快照或制作视频剪辑,请考虑使用现有的相机应用。如果要开发自定义相机功能,请参阅本文的构建相机应用部分。
* 前台 Service 要求 - 您的应用何时与相机交互?在 Android 9(API 级别 28)及更高版本中,在后台运行的应用无法访问相机。因此,您应该在应用于前台运行或作为前台服务的一部分时使用相机。
* 存储 - 您应用生成的图像或视频是否打算只对您的应用可见,还是说可以共享给其他应用(例如 Gallery)或媒体和社交应用使用?您是否想让照片和视频在您的应用卸载后仍然可用?请查看保存媒体文件部分,了解如何实现这些选项。

基础知识
Android 框架支持通过 android.hardware.camera2 API 或相机 Intent 捕获图像和视频。以下是相关的类:android.hardware.camera2此软件包是用于控制设备相机的主要 API。当您构建相机应用时,该软件包可用于拍摄照片或视频。Camera此类是用于控制设备相机的旧版 API,现已弃用。SurfaceView此类用于向用户呈现实时相机预览。MediaRecorder此类用于记录来自相机的视频。IntentMediaStore.ACTION_IMAGE_CAPTURE 或 MediaStore.ACTION_VIDEO_CAPTURE 的 Intent 操作类型可用于捕获图像或视频,而无需直接使用 Camera 对象。清单声明
在开始使用 Camera API 开发应用之前,您应确保您的清单具有相应的声明,以允许使用相机硬件和其他相关功能。
* 相机权限 - 您的应用必须请求使用设备相机的权限。

注意:如果您通过调用现有的相机应用来使用相机,则您的应用无需请求此权限。
* 相机功能 - 您的应用必须声明对相机功能的使用,例如:

如需相机功能列表,请参阅功能参考资料清单。
向清单添加相机功能会造成 Google Play 阻止您的应用安装到不包含相机或不支持指定相机功能的设备上。如需了解有关将基于功能的过滤与 Google Play 结合使用的更多信息,请参阅Google Play 和基于功能的过滤。
如果您的应用可以使用相机或相机功能进行适当的操作,但却未获取该功能,则您应在清单中添加 android:required 属性并将其设置为 false 以进行指定:

* 存储权限 - 如果您的应用将图像或视频保存至设备的外部存储装置(SD 卡),则您还必须在清单中指定此内容。

* 音频录制权限 - 如要通过视频捕获来录制音频,应用必须请求音频捕获权限。

* 位置权限 - 如果您的应用使用 GPS 位置信息标记图像,则您必须请求 ACCESS_FINE_LOCATION 权限。请注意,如果您的应用适配 Android 5.0(API 级别 21)或更高版本,则您还需声明您的应用使用设备 GPS:

如需了解关于获取用户位置的更多信息,请参阅位置策略。

使用现有相机应用
要在应用中启用拍照或视频录制功能而不添加大量额外代码,一种快捷方法就是使用 Intent 调用现有的 Android 相机应用。如需了解详细信息,请查看简单拍照和简单录制视频培训课程。构建相机应用
一些开发者可能需要相机界面根据应用的外观进行自定义或提供特殊功能。编写您自己的拍照代码可为您的用户提供一种更有吸引力的体验。
注意:以下指南适用于已弃用的旧版 Camera API。我们建议您使用更新的 android.hardware.camera2 API 来打造更新颖、先进的相机应用。
为应用创建自定义相机界面的一般步骤如下:
* 检测和访问相机 - 创建代码以检查设备是否配有相机并请求访问权限。
* 创建预览类 - 创建一个扩展 SurfaceView 并实现 SurfaceHolder 接口的相机预览类。此类预览来自摄像机的实时图像。
* 构建预览布局 - 拥有相机预览类后,创建一个融合预览和您想要的界面控件的视图布局。
* 为捕获设置侦听器 - 为界面控件连接侦听器,以便启用图像或视频捕获来响应用户操作,例如按下按钮。
* 捕获并保存文件 - 创建用于捕获图片或视频并保存输出的代码。
* 释放相机 - 在用完相机之后,您的应用必须正确地释放相机,以便其他应用使用。

相机硬件是一个共享资源,因此必须小心管理,以便您的应用不会与其他可能也要用到相机的应用发生冲突。接下来的部分将讨论如何检测相机硬件、如何请求相机访问权限、如何捕获图片或视频,以及当您的应用用完相机后如何释放相机资源。
error注意:当您的应用用完相机后,请记得通过调用 Camera.release() 来释放 Camera 对象!如果您的应用没有妥善释放相机,则所有对相机的后续访问(包括您应用的访问),都将失败并且可能会导致您的应用或其它应用关闭。检测相机硬件
如果您的应用没有特别要求相机使用清单声明,则您应检查相机在运行时是否可用。如要执行此检查,请使用 PackageManager.hasSystemFeature() 方法,如下方示例代码中所示:

/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) 
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA))
        // this device has a camera
        return true;
     else 
        // no camera on this device
        return false;
    

Android 设备可拥有多个摄像头,例如,一个用于摄影的后置摄像头和一个用于视频通话的前置摄像头。在 Android 2.3(API 级别 9)及更高版本中,您可以使用 Camera.getNumberOfCameras() 方法检查设备上的可用摄像头数量。访问相机
如果您已确定应用所在的设备配有相机,则您必须通过获取 Camera 实例来请求其访问权限(除非您使用 Intent 访问相机)。
如要访问主摄像头,请使用 Camera.open() 方法并确保捕获任何异常,如下方代码所示:

/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance()
    Camera c = null;
    try 
        c = Camera.open(); // attempt to get a Camera instance
    
    catch (Exception e)
        // Camera is not available (in use or does not exist)
    
    return c; // returns null if camera is unavailable

error注意:使用 Camera.open() 方法时,请时常检查异常。当相机正在使用或不存在时,未能检查异常将导致系统关闭您的应用。
在运行 Android 2.3(API 级别 9)或更高版本的设备上,您可以使用 Camera.open(int) 访问特定摄像头。上述示例代码将访问设备的第一个后置摄像头(该设备有多个摄像头)。检查相机功能
获取相机的访问权限后,您可以使用 Camera.getParameters() 方法获取有关相机功能的详细信息,还可以检查返回的 Camera.Parameters 对象,以获取受支持的功能。当使用 API 级别 9 或更高级别时,请使用 Camera.getCameraInfo() 确定设备的摄像头是前置还是后置,以及图像的屏幕方向。创建预览类
为了能更高效地拍照或录制视频,用户必须能够看到设备相机所捕捉的图像。相机预览类是一个 SurfaceView,可以显示来自相机的实时图像数据,以便用户可以构图并捕捉招聘或视频。
以下示例代码演示如何创建可包含在 View 布局中的基础相机预览类。此类实现 SurfaceHolder.Callback,以便捕获用于创建和销毁视图的回调事件,这些是分配相机预览输入的必需事件。

/** A basic Camera preview class */
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback 
    private SurfaceHolder mHolder;
    private Camera mCamera;

    public CameraPreview(Context context, Camera camera) 
        super(context);
        mCamera = camera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    

    public void surfaceCreated(SurfaceHolder holder) 
        // The Surface has been created, now tell the camera where to draw the preview.
        try 
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
         catch (IOException e) 
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        
    

    public void surfaceDestroyed(SurfaceHolder holder) 
        // empty. Take care of releasing the Camera preview in your activity.
    

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null)
          // preview surface does not exist
          return;
        

        // stop preview before making changes
        try 
            mCamera.stopPreview();
         catch (Exception e)
          // ignore: tried to stop a non-existent preview
        

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try 
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

         catch (Exception e)
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        
    

如果您想为相机预览设置特定尺寸,请在 surfaceChanged() 方法中进行设置,如上述注释中所述。设置预览尺寸时,您必须使用来自 getSupportedPreviewSizes() 的值。请勿在 setPreviewSize() 方法中设置任意值。
star注意:随着 Android 7.0(API 级别 24)及更高版本引入多窗口功能,您无法再假设预览的宽高比与您的 Activity 相同,即便调用 setDisplayOrientation() 也是如此。根据窗口尺寸和屏幕宽高比,你可能需要使用 Letterbox 布局将横向的相机预览适配到纵向布局中,或反之亦然。
在布局中放置预览
相机预览类(如上一部分中的示例)必须与用于拍照或录制视频的其他界面控件一起放置在 Activity 的布局中。本部分将为您展示如何为预览构建基本布局和 Activity。
以下布局代码提供一个可用于显示相机预览的基本视图。在本例中,FrameLayout 元素将会成为相机预览类的容器。使用此布局类型可将其他照片信息或空间覆盖在实时相机预览图像上。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
  <FrameLayout
    android:id="@+id/camera_preview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    />

  <Button
    android:id="@+id/button_capture"
    android:text="Capture"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    />
</LinearLayout>

在大多数设备上,相机预览的默认屏幕方向是横向。此示例布局指定水平(横向)布局,下方代码将应用的屏幕方向固定为横向。为了简化相机预览的渲染,您应通过在清单中添加如下内容来将应用的预览 Activity 屏幕方向改为横向。

<activity android:name=".CameraActivity"
          android:label="@string/app_name"

          android:screenOrientation="landscape">
          <!-- configure this activity to use landscape orientation -->

          <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

注意:相机预览不必处于横屏模式。从 Android 2.2(API 级别 8)开始,您可使用 setDisplayOrientation() 方法设置预览图像的旋转。为了在用户重定向手机时改变预览屏幕方向,请在您预览类的 surfaceChanged() 方法中,首先使用 Camera.stopPreview() 停止预览并更改屏幕方向,然后使用 Camera.startPreview() 重新启动预览。
在相机视图的 Activity 中,将您的预览类添加到上述示例的 FrameLayout 元素中。同时,您的相机 Activity 还必须确保在相机暂停或关闭时释放相机资源。以下示例展示如何修改相机 Activity 来附加创建预览类中所示的预览类。

public class CameraActivity extends Activity 
    private Camera mCamera;
    private CameraPreview mPreview;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Create an instance of Camera
        mCamera = getCameraInstance();

        // Create our Preview view and set it as the content of our activity.
        mPreview = new CameraPreview(this, mCamera);
        FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mPreview);
    

star注意:上述示例中的 getCameraInstance() 方法引用访问相机中的示例方法。捕获照片
构建预览类及显示预览类的视图布局后,您便可以开始使用应用捕获图像。在应用代码中,您必须为界面控件设置侦听器,以便通过拍照来响应用户操作。
为检索照片,请使用 Camera.takePicture() 方法。该方法采用三个参数,这些参数均从相机接收数据。为了接收 JPEG 格式的数据,您必须实现 Camera.PictureCallback 界面以接收图像数据并将其写入文件。以下代码展示 Camera.PictureCallback 界面的一个基本实现,该实现用于保存来自相机的图像。

private PictureCallback mPicture = new PictureCallback() 

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

        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null)
            Log.d(TAG, "Error creating media file, check storage permissions");
            return;
        

        try 
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
         catch (FileNotFoundException e) 
            Log.d(TAG, "File not found: " + e.getMessage());
         catch (IOException e) 
            Log.d(TAG, "Error accessing file: " + e.getMessage());
        
    
;

通过调用 Camera.takePicture() 方法触发图像捕获。以下示例代码展示如何使用按钮 View.OnClickListener 调用该方法。

// Add a listener to the Capture button
Button captureButton = (Button) findViewById(R.id.button_capture);
captureButton.setOnClickListener(
    new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            // get an image from the camera
            mCamera.takePicture(null, null, picture);
        
    
);

star注意:以下示例中的 mPicture 成员引用上述示例代码。
error注意:当您的应用用完相机后,请记得通过调用 Camera.release() 来释放 Camera 对象!如需了解有关如何释放相机的信息,请参阅释放相机。捕获视频
使用 Android 框架捕获视频需要注意对 Camera 对象的管理以及与 MediaRecorder 类的协调。使用 Camera 录制视频时,您必须管理 Camera.lock() 和 Camera.unlock() 调用,以允许 MediaRecorder 访问相机硬件,Camera.open() 和 Camera.release() 调用除外。
star注意:从 Android 4.0(API 级别 14)开始,系统将自动为您管理Camera.lock() 和 Camera.unlock() 调用。
与使用设备相机拍照不同,捕获视频需要非常特殊的调用顺序。您必须严格遵循此调用顺序,才能成功为应用程序准备和捕获视频,详细步骤如下。
1. 打开相机 - 使用 Camera.open() 获取相机对象实例。
2. 连接预览 - 使用 Camera.setPreviewDisplay() 将 SurfaceView 连接到相机,以准备实时相机图像预览。
3. 开始预览 - 调用 Camera.startPreview() 以开始显示实时相机图像。
开始录制视频 - 要成功录制视频,必须完成下列步骤:

	1. 解锁相机 - 通过调用 Camera.unlock() 解锁相机以供 MediaRecorder 使用。
	2. 配置 MediaRecorder - 按此顺序在以下 MediaRecorder 方法中调用。如需了解详细信息,请参阅 MediaRecorder 参考文档。

		1. setCamera() - 设置要用于视频捕获的相机,使用应用程序的当前 Camera 实例。
		2. setAudiosource() - 设置音频源,使用 MediaRecorder.AudioSource.CAMCORDER。
		3. setVideoSource() - 设置视频源,使用 MediaRecorder.VideoSource.CAMERA。
		4. 设置视频的输出格式和编码。对于 Android 2.2(API 级别 8)及更高版本,请使用 MediaRecorder.setProfile 方法,并使用 CamcorderProfile.get() 获取配置文件实例。
		
			对于 Android 2.2 之前的版本,您必须设置视频的输出格式和编码参数:
				1. setOutputFormat() - 设置输出格式,指定默认设置或 MediaRecorder.OutputFormat.MPEG_4。
				2. setAudioEncoder() - 设置声音编码类型,指定默认设置或 MediaRecorder.AudioEncoder.AMR_NB。
				3. setVideoEncoder() - 设置视频编码类型,指定默认设置或 MediaRecorder.VideoEncoder.MPEG_4_SP。
		6. setOutputFile() - 设置输出文件,使用保存媒体文件部分示例方法中的 getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()。
		7. setPreviewDisplay() - 为您的应用指定 SurfaceView 预览布局元素。使用您在连接预览部分中指定的相同对象。

注意:您必须按此顺序调用上述 MediaRecorder 配置方法,否则您的应用将会遇到错误且视频录制将会失败。
3. 准备 MediaRecorder - 通过调用 MediaRecorder.prepare() 提供的配置设置准备 MediaRecorder。
4. 启动 MediaRecorder - 通过调用 MediaRecorder.start() 开始录制视频。
5. 停止录制视频 - 依次调用以下方法,以便成功完成视频录制:

	1. 停止 MediaRecorder - 通过调用 MediaRecorder.stop() 停止视频录制。
	2. 重置 MediaRecorder - (可选)通过调用 MediaRecorder.reset() 从录制器中移除配置设置。
	3. 释放 MediaRecorder - 通过调用 MediaRecorder.release() 释放 MediaRecorder。
	4. 锁定相机 - 锁定相机以便未来的 MediaRecorder 会话可通过调用 Camera.lock() 使用它。从 Android 4.0(API 级别 14)开始,除非 MediaRecorder.prepare() 调用失败,否则不需要此调用。
  1. 停止预览 - 当 Activity 结束对相机的使用时,使用 Camera.stopPreview() 停止预览。

  2. 释放相机 - 释放相机以便其他应用可通过调用 Camera.release() 使用它。

    注意:您也可不先创建相机预览并跳过上述流程的前几个步骤,直接使用 MediaRecorder。但用户通常希望在开始录制之前能看到预览,所以此情况不在这里讨论。
    提示:如果您的应用通常用于录制视频,请在开始预览之前将 setRecordingHint(boolean) 设置为 true。此设置有助于减少开始录制所需的时间。配置 MediaRecorder
    当使用 MediaRecorder 类录制视频时,您必须按指定顺序执行配置步骤,然后调用 MediaRecorder.prepare() 方法来检查并实现配置。以下示例代码演示如何正确配置和准备用于录制视频的 MediaRecorder 类。

private boolean prepareVideoRecorder()

    mCamera = getCameraInstance();
    mediaRecorder = new MediaRecorder();

    // Step 1: Unlock and set camera to MediaRecorder
    mCamera.unlock();
    mediaRecorder.setCamera(mCamera);

    // Step 2: Set sources
    mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
    mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

    // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
    mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

    // Step 4: Set output file
    mediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());

    // Step 5: Set the preview output
    mediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());

    // Step 6: Prepare configured MediaRecorder
    try 
        mediaRecorder.prepare();
     catch (IllegalStateException e) 
        Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
        return false;
     catch (IOException e) 
        Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
        releaseMediaRecorder();
        return false;
    
    return true;

在 Android 2.2(API 级别 8)之前,您必须直接设置输出格式和编码格式参数,而不是使用 CamcorderProfile。下方代码演示了此方法:

// Step 3: Set output format and encoding (for versions prior to API Level 8)
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);

以下是 MediaRecorder 视频录制参数的默认设置,但是,您可能需要为应用调整这些设置:
* setVideoEncodingBitRate()
* setVideoSize()
* setVideoFrameRate()
* setAudioEncodingBitRate()
* setAudioChannels()
* setAudioSamplingRate()

启动和停止 MediaRecorder
使用 MediaRecorder 类开始和停止视频录制时,您必须严格按照下列特定顺序执行操作。
1. 使用 Camera.unlock() 解锁相机
2. 配置 MediaRecorder,如上述代码示例所示
3. 使用 MediaRecorder.start() 开始录制
4. 录制视频
5. 使用 MediaRecorder.stop() 停止录制
6. 使用 MediaRecorder.release() 释放媒体录制器
7. 使用 Camera.lock() 锁定相机

以下示例代码演示如何接通按钮,以使其正确使用相机和 MediaRecorder 类开始和停止视频录制。
注意:完成视频录制后,请勿释放相机,否则预览将会停止。

private boolean isRecording = false;

// Add a listener to the Capture button
Button captureButton = (Button) findViewById(id.button_capture);
captureButton.setOnClickListener(
    new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            if (isRecording) 
                // stop recording and release camera
                mediaRecorder.stop();  // stop the recording
                releaseMediaRecorder(); // release the MediaRecorder object
                mCamera.lock();         // take camera access back from MediaRecorder

                // inform the user that recording has stopped
                setCaptureButtonText("Capture");
                isRecording = false;
             else 
                // initialize video camera
                if (prepareVideoRecorder()) 
                    // Camera is available and unlocked, MediaRecorder is prepared,
                    // now you can start recording
                    mediaRecorder.start();

                    // inform the user that recording has started
                    setCaptureButtonText("Stop");
                    isRecording = true;
                 else 
                    // prepare didn't work, release the camera
                    releaseMediaRecorder();
                    // inform user
                
            
        
    
);

star注意:在上面的示例中,prepareVideoRecorder() 方法引用了配置 MediaRecorder 部分中的示例代码。此方法负责锁定相机、配置和准备 MediaRecorder 实例。释放相机
相机是设备上所有应用的共享资源。应用可在获取 Camera 实例后使用相机;当您的应用暂停 (Activity.onPause()) 或停止使用相机时,您必须极为小心地释放相机对象。如果您的应用没有妥善释放相机,则所有对相机的后续访问(包括您应用的访问),都将失败并且可能会导致您的应用或其它应用关闭。
要释放 Camera 对象实例,请使用 Camera.release() 方法,如下方的示例代码所示。

public class CameraActivity extends Activity 
    private Camera mCamera;
    private SurfaceView preview;
    private MediaRecorder mediaRecorder;

    ...

    @Override
    protected void onPause() 
        super.onPause();
        releaseMediaRecorder();       // if you are using MediaRecorder, release it first
        releaseCamera();              // release the camera immediately on pause event
    

    private void releaseMediaRecorder()
        if (mediaRecorder != null) 
            mediaRecorder.reset();   // clear recorder configuration
            mediaRecorder.release(); // release the recorder object
            mediaRecorder = null;
            mCamera.lock();           // lock camera for later use
        
    

    private void releaseCamera()
        if (mCamera != null)
            mCamera.release();        // release the camera for other applications
            mCamera = null;
        
    

error注意:如果您的应用没有妥善释放相机,则所有对相机的后续访问(包括您应用的访问),都将失败并且可能会导致您的应用或其它应用关闭。保存媒体文件
用户创建的图片和视频等媒体文件,应保存至设备的外部储存目录(SD 卡),以节省系统空间,并使用户不使用其设备也能访问这些文件。您可以将媒体文件保存至设备上的多个目录位置

以上是关于Camera1 API详解的主要内容,如果未能解决你的问题,请参考以下文章

Camera1 API详解

Camera1 API使用规范

Android之camera1和2的简单使用

Android之camera1和2的简单使用

安卓camera2 API获取YUV420_888格式详解

Android API 级别 23 上的相机 1 包