API Tiện ích Camera2

Lưu ý: Trang này đề cập đến gói Camera2. Bạn nên sử dụng CameraX, trừ phi ứng dụng yêu cầu các tính năng cụ thể ở cấp thấp trong Camera2. Cả CameraX và Camera2 đều hỗ trợ Android 5.0 (API cấp 21) trở lên.

Camera2 cung cấp API Extensions dùng cho việc truy cập vào các tiện ích mà nhà sản xuất thiết bị đã triển khai trên nhiều thiết bị Android. Để biết danh sách các chế độ được hỗ trợ của tiện ích, hãy xem bài viết Tiện ích dành cho máy ảnh.

Để biết danh sách các thiết bị hỗ trợ tiện ích, hãy xem bài viết Thiết bị được hỗ trợ.

Cấu trúc tiện ích

Hình ảnh sau đây cho thấy cấu trúc của các tiện ích máy ảnh.

Hình 1. Cấu trúc của các tiện ích máy ảnh

Ứng dụng Camera2 có thể sử dụng các tiện ích thông qua API Camera2. API Camera2 cung cấp nhiều cách để truy vấn các tiện ích có sẵn, định cấu hình một phiên máy ảnh của tiện ích và giao tiếp với thư viện OEM của Tiện ích máy ảnh. Việc này cho phép ứng dụng của bạn dùng các tiện ích như Ban đêm, HDR, Tự động, Bokeh hoặc Làm đẹp khuôn mặt.

Kiểm tra khả năng tương thích của API Tiện ích Camera2 của thiết bị máy ảnh

Đoạn mã sau đây sẽ kiểm tra xem thiết bị có hỗ trợ API Tiện ích Camera2 hay không. Không phải thiết bị nào cũng hỗ trợ tiện ích hoặc thiết bị có thể hỗ trợ một số tiện ích. Đoạn mã này sẽ trả về một danh sách mã máy ảnh tương thích có hỗ trợ tiện ích máy ảnh.

Kotlin


private fun getExtensionCameraIds(cameraManager: CameraManager): List<String> =
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        cameraManager.cameraIdList.filter { cameraId ->
            val characteristics = cameraManager.getCameraCharacteristics(cameraId)
            val extensionCharacteristics =
                cameraManager.getCameraExtensionCharacteristics(cameraId)
            val capabilities =
                characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
            extensionCharacteristics.supportedExtensions.isNotEmpty() &&
                    capabilities?.contains(
                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
                    ) ?: false
        }
    } else emptyList()

Java


private List<String> getExtensionCameraIds(CameraManager cameraManager)
        throws CameraAccessException {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        return Arrays.stream(cameraManager.getCameraIdList()).filter(cameraId -> {
            try {
                CameraCharacteristics characteristics =
                        cameraManager.getCameraCharacteristics(cameraId);
                CameraExtensionCharacteristics extensionCharacteristics =
                        cameraManager.getCameraExtensionCharacteristics(cameraId);
                IntStream capabilities =
                    Arrays.stream(
                                characteristics.get(
                                        CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES
                                )
                        );
                return !extensionCharacteristics.getSupportedExtensions().isEmpty() &&
                       capabilities.anyMatch(capability -> capability == CameraCharacteristics
                                        .REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
                        );
            } catch (CameraAccessException e) {
                throw new RuntimeException(e);
            }
        }).collect(Collectors.toList());
    } else {
        return Collections.emptyList();
    }
}

Tạo CameraExtensionSession bằng API Tiện ích Camera2

Khi được dùng với các thiết bị tương thích, API Tiện ích Camera2 sẽ cho phép bạn truy cập vào một số tiện ích máy ảnh nhất định. Đoạn mã sau đây cho thấy một ví dụ về cách tạo CameraExtensionSession để sử dụng chế độ chụp ban đêm cho ứng dụng Camera2 hiện có.

Kotlin


private val captureCallbacks = object : CameraExtensionSession.ExtensionCaptureCallback() {
    // Implement Capture Callbacks
}
private val extensionSessionStateCallback = object : CameraExtensionSession.StateCallback() {
    override fun onConfigured(session: CameraExtensionSession) {
        cameraExtensionSession = session
        try {
            val captureRequest =
                cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
                    addTarget(previewSurface)
                }.build()
            session.setRepeatingRequest(
                captureRequest,
                Dispatchers.IO.asExecutor(),
                captureCallbacks
            )
        } catch (e: CameraAccessException) {
            Snackbar.make(
                previewView,
                "Failed to preview capture request",
                Snackbar.LENGTH_SHORT
            ).show()
            requireActivity().finish()
        }
    }

    override fun onClosed(session: CameraExtensionSession) {
        super.onClosed(session)
        cameraDevice.close()
    }

    override fun onConfigureFailed(session: CameraExtensionSession) {
        Snackbar.make(
            previewView,
            "Failed to start camera extension preview",
            Snackbar.LENGTH_SHORT
        ).show()
        requireActivity().finish()
    }
}

private fun startExtensionSession() {
    val outputConfig = arrayListOf(
        OutputConfiguration(stillImageReader.surface),
        OutputConfiguration(previewSurface)
    )
    val extensionConfiguration = ExtensionSessionConfiguration(
        CameraExtensionCharacteristics.EXTENSION_NIGHT,
        outputConfig,
        Dispatchers.IO.asExecutor(),
        extensionSessionStateCallback
    )
    cameraDevice.createExtensionSession(extensionConfiguration)
}

Java


private CameraExtensionSession.ExtensionCaptureCallback captureCallbacks =
        new CameraExtensionSession.ExtensionCaptureCallback() {
            // Implement Capture Callbacks
        };

private CameraExtensionSession.StateCallback extensionSessionStateCallback =
        new CameraExtensionSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraExtensionSession session) {
                cameraExtensionSession = session;
                try {
                    CaptureRequest.Builder captureRequestBuilder =
                            cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                    captureRequestBuilder.addTarget(previewSurface);
                    CaptureRequest captureRequest = captureRequestBuilder.build();
                    session.setRepeatingRequest(captureRequest, backgroundExecutor, captureCallbacks);
                } catch (CameraAccessException e) {
                    Snackbar.make(
                            previewView,
                            "Failed to preview capture request",
                            Snackbar.LENGTH_SHORT
                    ).show();
                    requireActivity().finish();
                }
            }

            @Override
            public void onClosed(@NonNull CameraExtensionSession session) {
                super.onClosed(session);
                cameraDevice.close();
            }

            @Override
            public void onConfigureFailed(@NonNull CameraExtensionSession session) {
                Snackbar.make(
                        previewView,
                        "Failed to start camera extension preview",
                        Snackbar.LENGTH_SHORT
                ).show();
                requireActivity().finish();
            }
        };

private void startExtensionSession() {
    ArrayList<OutputConfiguration> outputConfig = new ArrayList<>();
    outputConfig.add(new OutputConfiguration(stillImageReader.getSurface()));
    outputConfig.add(new OutputConfiguration(previewSurface));
    ExtensionSessionConfiguration extensionConfiguration = new ExtensionSessionConfiguration(
            CameraExtensionCharacteristics.EXTENSION_NIGHT,
            outputConfig,
            backgroundExecutor,
            extensionSessionStateCallback
    );
}

Tài nguyên khác

Để biết thêm thông tin, hãy xem CameraExtensionCharacteristics và xem các mẫu công khai của CameraX Extensions API (API tiện ích CameraX) để biết thêm.