使用Camera2,让相机功能更灵活

使用Camera2 API,开发者可以实现更多的相机功能,如手动对焦、手动曝光、原生RAW图像捕获等
首页 新闻资讯 行业资讯 使用Camera2,让相机功能更灵活

Camera2介绍

Camera2 API是Android系统中用于访问相机功能的一套API。它提供了更强大和灵活的相机控制能力,相比之前的Camera API,Camera2 API支持更多的功能和更高的性能。

使用Camera2 API,开发者可以实现更多的相机功能,如手动对焦、手动曝光、原生RAW图像捕获等。同时,Camera2 API也提供了更好的性能和更低的延迟,使得相机应用在性能要求较高的场景下能够更好地发挥作用。

在Android系统中,相机功能的实现离不开Camera2 API的支持,因此对于需要使用相机功能的应用开发者来说,熟悉并掌握Camera2 API是非常重要的。

Camera2主要包括以下几个重要组件:

  1. CameraManager:相机管理器,用于检测和连接可用的相机设备。

  2. CameraDevice:相机设备,代表一个物理相机设备,可以打开、配置和关闭相机设备。

  3. CameraCaptureSession:相机捕获会话,用于发送捕获请求和接收捕获结果,可以预览、拍照、录像等。

  4. CameraCharacteristics:相机特性,提供了相机设备的静态信息,如支持的参数、分辨率、对焦模式等。

使用Camera2,开发者可以更灵活地控制相机的功能和参数,实现更丰富的相机应用程序。

Camera2使用

  1. 检查相机权限:确保在AndroidManifest.xml文件中添加了相机权限

<uses-permission android:name="android.permission.CAMERA"/>
  1. 设置相机预览

  • 创建一个TextureView用于显示相机预览画面。

  • 使用CameraManager获取相机设备的ID,并打开相机。

  • 创建CameraCaptureSession用于预览。

  1. 拍照

  • 创建一个按钮用于触发拍照操作。

  • 当用户点击按钮时,使用CameraCaptureSession进行拍照操作。

  • 保存拍摄的照片到指定的文件路径。

  1. 处理相机权限和生命周期

  • 在onResume方法中检查相机权限,并打开相机。

  • 在onPause方法中关闭相机,释放相关资源。

示例代码:

<?xml version="1.0"encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><TextureView
        android:id="@+id/textureView"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_weight="1"/><Button
        android:onClick="takePicture"android:id="@+id/btnCapture"android:layout_width="100dp"android:layout_height="wrap_content"android:text="拍照"/></LinearLayout>
publicclass CameraActivity extends AppCompatActivity {

    private static finalintREQUEST_CAMERA_PERMISSION=200;private static finalintREQUEST_WRITE_EXTERNAL_STORAGE_PERMISSION=201;private CameraManager cameraManager;private String cameraId;private CameraDevice cameraDevice;private CameraCaptureSession cameraCaptureSession;private CaptureRequest.Builder captureRequestBuilder;private ImageReader imageReader;private TextureView textureView;private final TextureView.SurfaceTextureListener surfaceTextureListener=new TextureView.SurfaceTextureListener(){@Overridepublicvoid onSurfaceTextureAvailable(SurfaceTexture surface,intwidth,intheight){
            openCamera();}@Overridepublicvoid onSurfaceTextureSizeChanged(SurfaceTexture surface,intwidth,intheight){
        }@OverridepublicbooleanonSurfaceTextureDestroyed(SurfaceTexture surface){returnfalse;}@Overridepublicvoid onSurfaceTextureUpdated(SurfaceTexture surface){
        }
    };private final CameraDevice.StateCallback stateCallback=new CameraDevice.StateCallback(){@Overridepublicvoid onOpened(@NonNullCameraDevice camera){
            cameraDevice=camera;createCameraPreview();}@Overridepublicvoid onDisconnected(@NonNullCameraDevice camera){
            cameraDevice.close();}@Overridepublicvoid onError(@NonNullCameraDevice camera,interror){
            cameraDevice.close();cameraDevice=null;}
    };private final CameraCaptureSession.StateCallback captureSessionStateCallback=new CameraCaptureSession.StateCallback(){@Overridepublicvoid onConfigured(@NonNullCameraCaptureSessionsession){
            cameraCaptureSession=session;try {
                captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(),null,null);} catch(CameraAccessException e){
                e.printStackTrace();}
        }@Overridepublicvoid onConfigureFailed(@NonNullCameraCaptureSessionsession){
        }
    };@Overrideprotected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);setContentView(R.layout.activity_camera);textureView=findViewById(R.id.textureView);textureView.setSurfaceTextureListener(surfaceTextureListener);}@Overrideprotected void onResume(){
        super.onResume();if(textureView.isAvailable()){
            openCamera();}else{
            textureView.setSurfaceTextureListener(surfaceTextureListener);}
    }@Overrideprotected void onPause(){
        closeCamera();super.onPause();}

    private void openCamera(){
        cameraManager=(CameraManager)getSystemService(Context.CAMERA_SERVICE);try {
            cameraId=cameraManager.getCameraIdList()[0];if(ActivityCompat.checkSelfPermission(this,Manifest.permission.CAMERA)!=PackageManager.PERMISSION_GRANTED){
                ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},REQUEST_CAMERA_PERMISSION);return;}
            cameraManager.openCamera(cameraId,stateCallback,null);} catch(CameraAccessException e){
            e.printStackTrace();}
    }

    private void createCameraPreview(){
        SurfaceTexture texture=textureView.getSurfaceTexture();texture.setDefaultBufferSize(textureView.getWidth(),textureView.getHeight());Surface surface=new Surface(texture);try {
            captureRequestBuilder=cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);captureRequestBuilder.addTarget(surface);cameraDevice.createCaptureSession(Collections.singletonList(surface),captureSessionStateCallback,null);} catch(CameraAccessException e){
            e.printStackTrace();}
    }

    private void closeCamera(){if(cameraCaptureSession!=null){
            cameraCaptureSession.close();cameraCaptureSession=null;}if(cameraDevice!=null){
            cameraDevice.close();cameraDevice=null;}
    }publicvoid takePicture(){if(cameraDevice==null){return;}
        CameraManager manager=(CameraManager)getSystemService(Context.CAMERA_SERVICE);try {
            CameraCharacteristics characteristics=manager.getCameraCharacteristics(cameraDevice.getId());Size[]jpegSizes=null;if(characteristics!=null){
                jpegSizes=characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP).getOutputSizes(ImageFormat.JPEG);}intwidth=640;intheight=480;if(jpegSizes!=null&&jpegSizes.length>0){
                width=jpegSizes[0].getWidth();height=jpegSizes[0].getHeight();}
            ImageReader reader=ImageReader.newInstance(width,height,ImageFormat.JPEG,1);List<Surface>outputSurfaces=new ArrayList<>(2);outputSurfaces.add(reader.getSurface());outputSurfaces.add(new Surface(textureView.getSurfaceTexture()));CaptureRequest.Builder captureBuilder=cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);captureBuilder.addTarget(reader.getSurface());captureBuilder.set(CaptureRequest.CONTROL_MODE,CameraMetadata.CONTROL_MODE_AUTO);introtation=getWindowManager().getDefaultDisplay().getRotation();captureBuilder.set(CaptureRequest.JPEG_ORIENTATION,ORIENTATIONS.get(rotation));Filefile=newFile(getExternalFilesDir(null),"pic.jpg");ImageReader.OnImageAvailableListener readerListener=new ImageReader.OnImageAvailableListener(){@Overridepublicvoid onImageAvailable(ImageReader reader){
                    Image image=null;try {
                        image=reader.acquireLatestImage();ByteBuffer buffer=image.getPlanes()[0].getBuffer();byte[]bytes=new byte[buffer.capacity()];buffer.get(bytes);save(bytes);} catch(FileNotFoundException e){
                        e.printStackTrace();} catch(IOException e){
                        e.printStackTrace();} finally {if(image!=null){
                            image.close();}
                    }
                }

                private voidsave(byte[]bytes)throws IOException {
                    OutputStream output=null;try {
                        output=new FileOutputStream(file);output.write(bytes);} finally {if(output!=null){
                            output.close();}
                    }
                }
            };reader.setOnImageAvailableListener(readerListener,null);final CameraCaptureSession.CaptureCallback captureListener=new CameraCaptureSession.CaptureCallback(){@Overridepublicvoid onCaptureCompleted(@NonNullCameraCaptureSessionsession,@NonNullCaptureRequest request,@NonNullTotalCaptureResult result){
                    super.onCaptureCompleted(session,request,result);Toast.makeText(CameraActivity.this,"Saved:"+file,Toast.LENGTH_SHORT).show();createCameraPreview();}
            };cameraDevice.createCaptureSession(outputSurfaces,new CameraCaptureSession.StateCallback(){@Overridepublicvoid onConfigured(@NonNullCameraCaptureSessionsession){
                    try {session.capture(captureBuilder.build(),captureListener,null);} catch(CameraAccessException e){
                        e.printStackTrace();}
                }@Overridepublicvoid onConfigureFailed(@NonNullCameraCaptureSessionsession){
                }
            },null);} catch(CameraAccessException e){
            e.printStackTrace();}
    }
}

在这个示例中,我们首先需要获取相机权限和存储权限,然后通过CameraManager打开相机,创建预览界面,并实现拍照功能。在拍照时,我们需要设置图片的大小、旋转角度等参数,并保存拍摄的照片。

Camera2优缺点

优点

  1. 「全面的控制」:Camera2 API提供了更多的相机控制,包括手动对焦、曝光、白平衡等功能,使得开发者可以更精细地控制相机的行为。

  2. 「性能优化」:Camera2 API在性能上进行了优化,能够更好地利用多核处理器和硬件加速功能,提高相机应用的运行效率。

  3. 「支持原生RAW格式」:Camera2 API支持原生的RAW图像捕获,使得摄影爱好者和专业摄影师可以更好地处理和编辑照片。

缺点

  1. 「复杂性」:相比于之前的Camera API,Camera2 API的使用复杂度更高,需要开发者具备更多的相机知识和经验。

  2. 「兼容性问题」:部分老旧的设备可能不支持Camera2 API,这会导致应用在这些设备上无法正常运行。

  3. 「学习曲线」:对于新手开发者来说,学习并掌握Camera2 API可能需要花费更多的时间和精力。

8    2023-11-27 08:21:49    Camera2 API,