如何在Android中使用Camera2实现预览与拍照功能?

Android实现Camera2预览和拍照效果,首先需要配置Camera2的相关参数,包括设置预览尺寸、格式和缓冲区。然后创建相机捕获会话来管理图像捕获过程,并使用SurfaceTexture作为预览显示。在拍照时,通过调用CaptureRequest.Builder添加拍照请求,并启动一个单次捕获会话来捕捉照片。

Android实现Camera2预览和拍照效果

如何在Android中使用Camera2实现预览与拍照功能?

背景介绍

Android平台上的相机应用开发主要依赖于两套接口:Camera API和Camera2 API,Camera API相对简单易用,但功能有限;而Camera2 API功能强大,支持更高级的相机控制,如手动对焦、曝光补偿等,能直接访问RAW图像数据,本文将详细介绍如何使用Camera2 API实现相机预览和拍照效果,以满足开发者对于高度自定义相机功能的需求。

目录

1、[环境配置](#1-环境配置)

2、[布局文件](#2-布局文件)

3、[权限配置](#3-权限配置)

4、[Camera2预览](#4-camera2预览)

创建TextureView容器

监听TextureView状态

5、[Camera2拍照](#5-camera2拍照)

创建CaptureRequest.Builder

如何在Android中使用Camera2实现预览与拍照功能?

设置拍照参数

捕获拍照结果

6、[完整代码示例](#6-完整代码示例)

7、[(#7-

1. 环境配置

确保你的开发环境已安装Android Studio,并且项目的编译SDK版本为21或以上,因为Camera2 API是在API level 21(Lollipop)中引入的。

2. 布局文件

res/layout/activity_main.xml文件中定义界面布局,包括一个用于预览的TextureView和一个用于显示拍照结果的ImageView,以及一个触发拍照功能的Button。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <TextureView
        android:id="@+id/texture_view_camera2"
        android:layout_width="match_parent"
        android:layout_height="300dp" />
    <ImageView
        android:id="@+id/image_view_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/texture_view_camera2" />
    <Button
        android:id="@+id/button_capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/image_view_result"
        android:layout_centerHorizontal="true"
        android:text="Capture" />
</RelativeLayout>

3. 权限配置

AndroidManifest.xml中添加相机和存储权限配置,以确保应用能够访问相机设备和存储空间。

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera2.full" />

4. Camera2预览

如何在Android中使用Camera2实现预览与拍照功能?

创建TextureView容器

创建一个用于显示相机预览的TextureView。

private TextureView textureView;

onCreate方法中初始化TextureView并设置其SurfaceTextureListener。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    textureView = findViewById(R.id.texture_view_camera2);
    textureView.setSurfaceTextureListener(surfaceTextureListener);
}

监听TextureView状态

创建一个SurfaceTextureListener来监听TextureView的状态变化,当TextureView准备好时,开启相机并开始预览。

private final TextureView.SurfaceTextureListener surfaceTextureListener = new TextureView.SurfaceTextureListener() {
    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        openCamera();
    }
    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
    @Override
    public void onSurfaceTextureDestroyed(SurfaceTexture surface) {}
    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
};

5. Camera2拍照

创建CaptureRequest.Builder

在打开相机后,创建一个CaptureRequest.Builder用于构建拍照请求。

private void createCaptureRequest() {
    try {
        final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureBuilder.addTarget(textureSurface);
        // Use the same AE and AF modes as the preview.
        captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
        setAutoFlash(captureBuilder);
        // Orientation
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, (sensorOrientation + rotation) % 360);
        cameraCaptureSession.stopRepeating();
        cameraCaptureSession.abortCaptures();
        cameraCaptureSession.setRepeatingRequest(null, null, mCaptureCallback);
        cameraCaptureSession.capture(captureBuilder.build(), null, mCaptureCallback);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

设置拍照参数

在拍照前,需要锁定焦点并设置其他拍照参数。

private void lockFocus() {
    try {
        // Reset the auto-focus trigger
        captureBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
        setAutoFlash(captureBuilder);
        createCaptureSession(captureBuilder);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

捕获拍照结果

在拍照完成后,通过回调函数获取拍照结果并进行处理。

private final CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() {
    private void process(Result result) {
        switch (result.getResultCode()) {
            case CameraMetadata.RESULT_SUCCESS:
                Log.i(TAG, "Success");
                break;
            case CameraMetadata.RESULT_MAX_BYTES_EXCEEDED:
                Log.e(TAG, "Exceeded max bytes");
                break;
            default:
                Log.e(TAG, "Unknown result code: " + result.getResultCode());
                break;
        }
    }
};

6. 完整代码示例

以下是一个完整的示例,展示了如何在Android中使用Camera2 API实现相机预览和拍照功能,由于篇幅限制,以下代码仅展示了关键部分,请根据实际需求进行补充和完善。

public class MainActivity extends AppCompatActivity {
    private TextureView textureView;
    private Button buttonCapture;
    private ImageView imageViewResult;
    private CameraDevice cameraDevice;
    private CameraCaptureSession cameraCaptureSession;
    private CaptureRequest.Builder captureBuilder;
    private Size imageDimension;
    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
    private static final int REQUEST_CAMERA_PERMISSION = 200;
    private static final String TAG = "AndroidCameraApi";
    private static final int STATE_PREVIEW = 0;
    private static final int STATE_WAITING_LOCK = 1;
    private static final int STATE_WAITING_PRE_CAPTURE = 2;
    private static final int STATE_WAITING_NON_PRE_CAPTURE = 3;
    private static final int STATE_PICTURE_TAKEN = 4;
    private static final int MAX_WIDTH = 1920;
    private static final int MAX_HEIGHT = 1080;
    private static final int NATIVE_ASPECT_RATIO = AspectRatio.RATIO_16_9;
    private int mState = STATE_PREVIEW;
    private Semaphore mCameraOpenCloseLock = new Semaphore(1);
    private boolean mFlashSupported = false;
    private int mSensorOrientation;
    private CameraCharacteristics mCharacteristics;
    private CameraManager mCameraManager;
    private String mCameraId;
    private HandlerThread mBackgroundThread;
    private Handler mBackgroundHandler;
    private int mImageFormat = ImageFormat.JPEG;
    private int mJPEGQuality = 100;
    private long mLastClickTime = 0;
    private static final int MSG_AUTO_FOCUS = 1;
    private AutoFocusCallback mAutoFocusCallback = new AutoFocusCallback() {
        @Override
        public void onAutoFocus(boolean success, CameraCaptureSession cameraCaptureSession) {
            mState = success ? STATE_WAITING_PRE_CAPTURE : STATE_WAIT_NON_PRE_CAPTURE;
            if (!success) {
                enableCapture(false); // Retry after some delay.
            } else {
                lockFocus(); // Start capturing images.
            }
        }
    };
    private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            openCamera();
        }
        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { }
        @Override
        public void onSurfaceTextureDestroyed(SurfaceTexture surface) { }
        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) { }
    };
    private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) { ... }
        @Override
        public void onDisconnected(@NonNull CameraDevice camera) { ... }
        @Override
        public void onError(@NonNull CameraDevice camera, int error) { ... }
    };
    private final CameraCaptureSession.StateCallback mSessionStateCallback = new CameraCaptureSession.StateCallback() { ... };
    private final CameraDevice.StateCallback mSessionReadyCallback = new CameraDevice.StateCallback() { ... };
    private final CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() { ... };
    private final CameraCaptureSession.StateCallback mPreviewStateCallback = new CameraCaptureSession.StateCallback() { ... };
    private final CameraCaptureSession.CaptureCallback mPreviewCaptureCallback = new CameraCaptureSession.CaptureCallback() { ... };
    private void createCameraPreviewSession() { ... }
    private void openCamera() { ... }
    private void unlockFocus() { ... }
    private void lockFocus() { ... }
    private void setAutoFlash(CaptureRequest.Builder requestBuilder) { ... }
    private void createCameraPreviewSession() throws CameraAccessException { ... }
    private void closeCamera() { ... }
    private void startBackgroundThread() { ... }
    private void stopBackgroundThread() { ... }
    private void takePicture() { ... }
    @Override
    protected void onResume() { ... }
    @Override
    protected void onPause() { ... }
    @Override
    protected void onDestroy() { ... }
    @Override
    public boolean onKeyDown(int keyCode, int event) { ... }
}

原创文章,作者:未希,如若转载,请注明出处:https://www.kdun.com/ask/1274357.html

本网站发布或转载的文章及图片均来自网络,其原创性以及文中表达的观点和判断不代表本网站。如有问题,请联系客服处理。

(0)
未希新媒体运营
上一篇 2024-11-08 23:10
下一篇 2024-11-08 23:13

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

产品购买 QQ咨询 微信咨询 SEO优化
分享本页
返回顶部
云产品限时秒杀。精选云产品高防服务器,20M大带宽限量抢购 >>点击进入