카메라 미리보기

참고: 이 페이지에서는 Camera2 패키지를 다룹니다. 앱에 Camera2의 특정 하위 수준 기능이 필요하지 않다면 CameraX를 사용하는 것이 좋습니다. CameraX와 Camera2는 모두 Android 5.0(API 수준 21) 이상을 지원합니다.

Android에서 카메라와 카메라 미리보기의 방향이 항상 같은 것은 아닙니다. 기기에서 사용할 수 있습니다.

카메라는 기기가 있든 없든 상관없이 기기에서 휴대전화, 태블릿 또는 컴퓨터입니다. 기기 방향이 변경되면 카메라 방향이 변경됩니다.

결과적으로, 카메라 앱은 일반적으로 카메라와 카메라 영상 간에 고정된 관계를 기기 방향 및 카메라 미리보기의 가로세로 비율일 수 있습니다. 사용자가 스마트폰이 세로 모드 방향이며 카메라 미리보기가 더 높은 것으로 가정됨 훨씬 작을 수 있습니다. 휴대전화 (및 카메라)가 가로 모드로 회전하면 카메라 미리보기는 높이보다 넓을 것으로 예상됩니다.

하지만 폴더블과 같은 새로운 폼 팩터로 인해 이러한 가정이 어려워지고 있습니다. 기기, 디스플레이 모드 예: 멀티 윈도우다중 디스플레이. 폴더블 기기는 디스플레이 크기와 가로세로 비율을 변경하지 않고 변경합니다. 방향을 설정할 수 있습니다. 멀티 윈도우 모드는 카메라 앱을 화면, 기기 방향에 관계없이 카메라 미리보기의 크기를 조정합니다. 다중 디스플레이 모드를 사용하면 작동하지 않을 수도 있는 보조 디스플레이를 사용할 수 있습니다 기본 디스플레이와 같은 방향이어야 합니다.

카메라 방향

Android 호환성 정의 카메라 이미지 센서가 '긴 이미지가 촬영되도록 방향을 설정해야 한다'고 카메라의 크기가 화면의 긴 크기와 정렬됩니다. 즉, 기기를 가로 방향으로 쥐고 카메라는 다음 위치에서 이미지를 캡처해야 합니다(MUST). 변경할 수 있습니다. 이는 기기의 자연스러운 작동 여부와 관계없이 방향 가로 모드가 기본인 기기뿐만 아니라 지정할 수 있습니다.

카메라-화면 배치는 카메라의 디스플레이 영역을 최대화합니다. 뷰파인더를 촬영할 수 있습니다. 또한 이미지 센서는 일반적으로 가로 모드 가로세로 비율로, 4:3이 가장 일반적입니다.

휴대전화 및 카메라 센서 모두 세로 모드 방향입니다.
그림 1. 휴대전화와 카메라 센서의 일반적인 관계 방향을 설정할 수 있습니다.

카메라 센서의 자연스러운 방향은 가로 모드입니다. 그림 1에서 센서는 카메라 (카메라가 찍힌 것과 같은 방향을 가리킴)에서 디스플레이)가 휴대전화를 기준으로 270도 회전하여 Android 호환성 정의

센서 회전을 앱에 노출하려면 camera2 API에는 SENSOR_ORIENTATION 상수입니다. 대부분의 휴대전화와 태블릿에서 기기가 센서 방향을 보고합니다. 270도, 전면 카메라의 경우 90도 (카메라의 경우 후면 카메라의 경우 기기의 긴 가장자리와 기기의 긴 가장자리에 대고 와야 합니다. 노트북 카메라는 일반적으로 0 또는 180도의 각도로 설정할 수 있습니다.

카메라 이미지 센서는 센서의 자연스러운 방향 (가로)에 따라 이미지 버퍼는 카메라 미리보기를 위해 SENSOR_ORIENTATION에서 지정한 각도입니다. 기기의 자연스러운 방향으로 똑바로 표시됩니다. 전면 카메라의 경우 시계 반대 방향으로 회전합니다. 시계 방향으로 할 수 있습니다.

예를 들어, 그림 1의 전면 카메라의 경우 이미지 버퍼는 생성된 함수는 다음과 같습니다.

카메라 센서가 가로 모드 방향으로 회전됨
            옆으로, 왼쪽 위

이미지를 미리 볼 수 있도록 시계 반대 방향으로 270도 회전해야 기기 방향과 일치합니다.

이미지가 똑바로 표시된 세로 방향의 카메라 센서

후면 카메라는 동일한 방향의 이미지 버퍼를 생성합니다. 위의 버퍼와 같지만 SENSOR_ORIENTATION는 90도입니다. 결과적으로 시계 방향으로 90도 회전합니다.

기기 회전

기기 회전은 기기가 원래 위치에서 회전한 각도입니다. 방향을 설정할 수 있습니다. 예를 들어 가로 방향 휴대전화에는 회전 방향에 따라 90도 또는 270도 회전

카메라 센서 이미지 버퍼는 센서 방향의 각도 외에 기기 회전이 카메라 미리보기가 똑바로 표시됩니다.

방향 계산

카메라 미리보기의 적절한 방향은 센서를 고려함 방향 및 기기 회전이 가능합니다.

센서 이미지 버퍼의 전체 회전은 공식:

rotation = (sensorOrientationDegrees - deviceOrientationDegrees * sign + 360) % 360

여기서 sign는 전면 카메라의 경우 1, 후면 카메라의 경우 -1입니다.

전면 카메라의 경우 이미지 버퍼가 센서의 자연스러운 방향). 후면 카메라의 경우 센서는 시계 방향으로 회전하는 것을 볼 수 있습니다.

deviceOrientationDegrees * sign + 360 표현식은 기기 회전을 변환합니다. 시계 반대 방향에서 시계 방향으로 변경하는 경우 (예: 270도를 시계 반대 방향으로 90도로 변환). 모듈로 연산은 결과를 360도 미만으로 조정합니다 (예: 540도 배율로 조정). 180도로 회전합니다.

API마다 기기 회전이 다르게 보고됩니다.

  • Display#getRotation() 사용자의 지점에서 기기를 시계 반대 방향으로 회전할 수 있습니다. 표시됩니다. 이 값은 위의 수식에 그대로 대입됩니다.
  • OrientationEventListener#onOrientationChanged() 는 사용자의 관점에서 기기의 시계 방향 회전을 반환합니다. 위 수식에서 사용할 값을 음수로 변환합니다.

전면 카메라

가로 모드 방향의 카메라 미리보기 및 센서, 센서
            있습니다.
그림 2. 카메라를 90도 회전한 카메라 미리보기 및 센서 사용할 수 있습니다.

다음은 그림 2의 카메라 센서에 의해 생성된 이미지 버퍼입니다.

이미지가 똑바로 표시된 가로 방향 카메라 센서

버퍼를 센서에 맞게 조정하려면 시계 반대 방향으로 270도 회전해야 합니다. 방향 (위의 카메라 방향 참고):

카메라 센서가 세로 방향으로 회전됨, 이미지가 옆으로 회전됨
            오른쪽 위

그런 다음 버퍼는 다시 시계 반대 방향으로 90도 회전하여 이로 인해 기기의 방향이 올바르게 바뀌도록 카메라 미리보기

카메라 센서가 가로 모드 방향으로 회전됨
            똑바로 서 있습니다.

다음은 카메라를 오른쪽으로 돌린 가로 모드 방향입니다.

카메라 미리보기와 센서가 가로 모드 방향에서 모두
            센서가 거꾸로 보이게 합니다.
그림 3. 휴대전화를 270도 돌린 상태의 카메라 미리보기 및 센서 또는 -90도)를 가로 방향으로 전환할 수 있습니다.

이미지 버퍼는 다음과 같습니다.

카메라 센서가 가로 모드 방향으로 회전했으며 이미지가 거꾸로 보입니다.
            감소합니다.

버퍼를 센서에 맞게 조정하려면 시계 반대 방향으로 270도 회전해야 합니다. 방향:

이미지가 옆으로 놓인 세로 방향으로 평가된 카메라 센서
            왼쪽 위

그런 다음 버퍼를 설명하기 위해 기기 회전

카메라 센서가 가로 모드 방향으로 회전됨
            똑바로 서 있습니다.

후면 카메라

일반적으로 후면 카메라의 센서 방향은 90도입니다( 기기 뒷면에서 바라보세요.) 카메라 미리보기의 방향을 설정할 때 센서 이미지 버퍼는 센서 회전량만큼 시계 방향으로 회전합니다. (전면 카메라처럼 시계 반대 방향이 아님)을 클릭한 다음 이미지가 버퍼는 기기 회전량에 따라 시계 반대 방향으로 회전합니다.

카메라 미리보기와 센서가 가로 모드 방향에서 모두
            센서가 거꾸로 보이게 합니다.
그림 4. 가로 모드의 후면 카메라가 있는 휴대전화 (270도 또는 -90도 회전)

다음은 그림 4에 표시된 카메라 센서의 이미지 버퍼입니다.

카메라 센서가 가로 모드 방향으로 회전했으며 이미지가 거꾸로 보입니다.
            감소합니다.

버퍼를 센서에 맞게 조정하려면 시계 방향으로 90도 회전해야 합니다. 방향:

이미지가 옆으로 놓인 세로 방향으로 평가된 카메라 센서
            왼쪽 위

그런 다음 버퍼는 기기를 고려하여 시계 반대 방향으로 270도 회전합니다. 순환게재:

카메라 센서가 가로 모드 방향으로 회전됨
            똑바로 서 있습니다.

가로세로 비율

디스플레이 가로세로 비율이 기기 방향이 변경될 때뿐만 아니라 멀티 윈도우에서 창의 크기가 조절될 때 폴더블이 접히고 펼쳐집니다. 앱 환경, 앱이 보조 디스플레이에서 열리는 시점 등입니다.

카메라 센서 이미지 버퍼는 UI로 사용되는 뷰파인더 UI 요소의 방향 및 가로세로 비율 기기 변경 여부와 관계없이 방향을 동적으로 변경합니다. 방향을 설정할 수 있습니다.

새로운 폼 팩터나 멀티 윈도우 또는 멀티 디스플레이 환경에서 앱이 카메라 미리보기의 방향이 기기와 동일하다고 가정합니다. (세로 또는 가로) 미리보기의 방향이 잘못 조정되거나 크기가 조정될 수 있음 오답이거나 두 개 모두일 수 있습니다

세로 모드 카메라 미리보기가 사용 설정된 펼친 폴더블 기기
            있습니다.
그림 5. 폴더블 기기가 세로 모드에서 가로 모드로 전환됨 가로세로 비율이지만 카메라 센서가 세로 모드 방향으로 유지됩니다.

그림 5에서 애플리케이션은 기기가 90도 회전했다고 잘못 가정했습니다. 시계 반대 방향의 각도, 따라서 앱이 미리보기를 같은 양만큼 회전했습니다.

폴더블 기기를 펼쳐서 카메라 미리보기가 똑바로 보이게 하고 있지만 찌그러져 있음
            잘못된 확장으로 인해
발생할 수 있습니다
그림 6. 폴더블 기기가 세로 모드에서 가로 모드로 전환됨 가로세로 비율이지만 카메라 센서가 세로 모드 방향으로 유지됩니다.

그림 6에서는 앱이 이미지 버퍼의 가로세로 비율을 카메라 미리보기 UI의 새 크기에 맞게 크기가 적절하게 조정되도록 합니다. 요소가 포함됩니다.

고정 방향 카메라 앱은 일반적으로 폴더블에서 문제가 발생하며 기타 대형 화면 기기(예: 노트북):

노트북의 카메라 미리보기가 똑바로 보이지만 앱 UI가 가로로 표시됩니다.
그림 7. 노트북 컴퓨터의 고정 방향 세로 모드 앱

그림 7에서는 카메라 앱의 UI가 가로로 되어 있습니다. 앱의 방향이 세로 모드로만 제한됩니다. 뷰파인더 이미지의 방향이 정확해야 합니다. 카메라 센서에 상대적입니다.

세로 모드 인셋

멀티 윈도우 모드를 지원하지 않는 카메라 앱 (resizeableActivity="false") 방향을 제한합니다. (screenOrientation="portrait"). 또는 screenOrientation="landscape") 큰 화면 기기에서 인셋 세로 모드로 배치하여 방향을 올바르게 잡을 수 있도록 확인할 수 있습니다

인셋 세로 모드 레터박스 (인셋) 세로 모드 전용 앱 가로 방향으로도 회전할 수 있습니다. 가로 모드 전용 앱은 가로 모드 방향으로 레터박스 처리됩니다. 디스플레이 가로세로 비율이 세로 모드입니다. 카메라 이미지가 회전하여 카메라 미리보기의 가로세로 비율에 맞게 잘린 이미지 크기를 조절하여 미리보기를 채웁니다

카메라 이미지의 가로세로 비율이 표시될 때 인셋 인물 사진 모드가 트리거됩니다. 센서와 애플리케이션 기본 활동의 가로세로 비율이 일치하지 않습니다.

노트북에서 적절한 세로 모드 방향의 카메라 미리보기 및 앱 UI
            넓은 미리보기 이미지가 세로 모드에 맞게 조정되고 잘립니다.
            방향을 설정할 수 있습니다.
그림 8. 인셋 세로 모드의 고정 방향 세로 모드 앱 사용 노트북입니다.

그림 8에서는 세로 모드 전용 카메라 앱이 회전되어 UI가 표시됩니다. 똑바로 세워져 있습니다. 차이가 있기 때문에 앱이 레터박스 처리됩니다. 세로 모드 앱과 가로 모드 디스플레이 간의 가로세로 비율 카메라 앱의 UI 회전을 보상하기 위해 미리보기 이미지가 회전했습니다. 세로 모드 삽입) 이미지에 맞게 이미지를 자르고 크기를 시야를 줄입니다.

회전, 자르기, 크기 조정

인셋 인물 사진 모드가 디스플레이의 세로 모드 전용 카메라 앱에 대해 호출됩니다. 가로 세로 비율이 있는 광고 소재:

노트북의 카메라 미리보기가 똑바로 보이지만 앱 UI가 가로로 표시됩니다.
그림 9. 노트북의 고정 방향 세로 모드 앱

앱이 세로 모드 방향으로 레터박스 처리됩니다.

앱이 세로 방향으로 회전하고 레터박스 처리됩니다. 이미지:
            오른쪽 상단으로 스와이프하는 것이 좋습니다.

카메라 이미지는 90도 회전되어 앱:

센서 이미지가 수직이 되도록 90도 회전했습니다.

이미지는 카메라 미리보기의 가로세로 비율에 맞게 잘린 후 미리보기를 채웁니다 (시야 감소).

잘린 카메라 이미지가 카메라 미리보기를 채우도록 조정되었습니다.

폴더블 기기에서는 카메라 센서의 방향이 세로 모드일 수 있습니다. 디스플레이의 가로세로 비율은 가로 모드입니다.

카메라 미리보기와 앱 UI가 넓고 펼쳐진 디스플레이의 옆으로 돌아갔습니다.
그림 10. 인물 사진 전용 카메라 앱이 있는 펼친 기기 카메라 센서와 디스플레이의 가로세로 비율이 서로 다를 수 있습니다.

카메라 미리보기가 회전하여 센서 방향에 맞게 조정되기 때문에 이미지가 뷰파인더에서 올바른 방향이지만 세로 모드 전용 앱에서는 있습니다.

인셋 세로 모드는 앱을 세로 방향으로만 레터박스 처리하면 됩니다. 앱과 카메라 미리보기의 방향을 적절하게 조정합니다.

카메라 미리보기가 포함된 세로 방향의 레터박스 처리된 앱
            똑바로 세웁니다.

API

Android 12 (API 수준 31)부터 앱은 인셋 세로 모드도 명시적으로 제어할 수 있습니다. 사용하여 SCALER_ROTATE_AND_CROP CaptureRequest의 속성 클래스에 대해 자세히 알아보세요.

기본값은 SCALER_ROTATE_AND_CROP_AUTO님, 이렇게 하면 시스템이 인셋 세로 모드를 호출할 수 있습니다. SCALER_ROTATE_AND_CROP_90 는 위에 설명된 인셋 세로 모드의 동작입니다.

일부 기기는 SCALER_ROTATE_AND_CROP 값을 지원하지 않습니다. 목록을 얻는 방법 참조 CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES

CameraX

Jetpack CameraX 라이브러리 카메라 뷰파인더를 만들어 센서 방향과 기기 회전은 간단한 작업입니다.

PreviewView 레이아웃 요소 카메라 미리보기를 생성하고 센서 방향을 자동으로 조정하며 기기 회전, 확장 등이 있습니다 PreviewView는 이미지 캡션 모델에 FILL_CENTER 배율 유형 - 이미지를 중앙에 배치하지만 크기에 맞게 자를 수 있음 PreviewView 중 하나입니다. 카메라 이미지를 레터박스에 표시하려면 배율 유형을 FIT_CENTER

PreviewView로 카메라 미리보기를 만들기 위한 기본사항을 알아보려면 다음을 참고하세요. 미리보기를 구현합니다.

전체 샘플 구현은 다음을 참조하세요. CameraXBasic 찾을 수 있습니다.

카메라 뷰파인더

Preview 사용 사례와 마찬가지로 CameraViewfinder 라이브러리는 카메라 미리보기를 간단하게 만들 수 있는 도구 모음을 제공합니다. CameraX Core에 종속되지 않으므로 앱에 원활하게 통합할 수 있습니다. 기존 Camera2 코드베이스에 액세스할 수 없습니다

대신 Surface 를 직접 CameraViewfinder 위젯을 사용하여 Camera2의 카메라 피드를 표시합니다.

CameraViewfinder는 내부적으로 TextureView 또는 SurfaceView를 사용합니다. 을 사용하여 카메라 피드를 표시하고 필요한 변환을 뷰파인더가 정확하게 표시됩니다. 여기에는 가로세로 비율, 크기, 회전 수정이 포함됩니다.

CameraViewfinder 객체에서 노출 영역을 요청하려면 다음을 실행해야 합니다. ViewfinderSurfaceRequest를 만듭니다.

이 요청에는 표면 해상도 및 카메라 기기 요구사항이 포함되어 있습니다. CameraCharacteristics의 정보

requestSurfaceAsync()에 전화 거는 중 노출 영역 제공자(TextureView 또는 SurfaceView이고 ListenableFutureSurface을 가져옵니다.

markSurfaceSafeToRelease()에 전화 거는 중 노출 영역 제공자에 노출 영역이 필요하지 않고 관련이 있다고 알림 리소스를 해제할 수 있습니다

Kotlin


fun startCamera(){
    val previewResolution = Size(width, height)
    val viewfinderSurfaceRequest =
        ViewfinderSurfaceRequest(previewResolution, characteristics)
    val surfaceListenableFuture =
        cameraViewfinder.requestSurfaceAsync(viewfinderSurfaceRequest)

    Futures.addCallback(surfaceListenableFuture, object : FutureCallback<Surface> {
        override fun onSuccess(surface: Surface) {
            /* create a CaptureSession using this surface as usual */
        }
        override fun onFailure(t: Throwable) { /* something went wrong */}
    }, ContextCompat.getMainExecutor(context))
}

자바


    void startCamera(){
        Size previewResolution = new Size(width, height);
        ViewfinderSurfaceRequest viewfinderSurfaceRequest =
                new ViewfinderSurfaceRequest(previewResolution, characteristics);
        ListenableFuture<Surface> surfaceListenableFuture =
                cameraViewfinder.requestSurfaceAsync(viewfinderSurfaceRequest);

        Futures.addCallback(surfaceListenableFuture, new FutureCallback<Surface>() {
            @Override
            public void onSuccess(Surface result) {
                /* create a CaptureSession using this surface as usual */
            }
            @Override public void onFailure(Throwable t) { /* something went wrong */}
        },  ContextCompat.getMainExecutor(context));
    }

SurfaceView

SurfaceView은(는) 미리보기가 없을 경우 카메라 미리보기를 쉽게 만들 수 있습니다. 처리가 필요하며 애니메이션이 적용되지 않습니다.

SurfaceView는 카메라 센서 이미지 버퍼를 이에 맞춰 자동으로 회전합니다. 센서 방향과 기기를 모두 고려하여 디스플레이 방향 있습니다. 그러나 이미지 버퍼는 SurfaceView에 맞게 조정됩니다. 가로 세로 비율을 고려하지 않은 크기입니다.

이미지 버퍼의 가로세로 비율이 가로세로와 일치하는지 확인해야 합니다. SurfaceView의 비율: 콘텐츠의 크기를 조정하여 달성할 수 있습니다. 구성요소의 SurfaceViewonMeasure() 메서드를 사용하여 축소하도록 요청합니다.

(computeRelativeRotation() 소스 코드는 아래 상대적 회전 참조).

Kotlin

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    val width = MeasureSpec.getSize(widthMeasureSpec)
    val height = MeasureSpec.getSize(heightMeasureSpec)

    val relativeRotation = computeRelativeRotation(characteristics, surfaceRotationDegrees)

    if (previewWidth > 0f && previewHeight > 0f) {
        /* Scale factor required to scale the preview to its original size on the x-axis. */
        val scaleX =
            if (relativeRotation % 180 == 0) {
                width.toFloat() / previewWidth
            } else {
                width.toFloat() / previewHeight
            }
        /* Scale factor required to scale the preview to its original size on the y-axis. */
        val scaleY =
            if (relativeRotation % 180 == 0) {
                height.toFloat() / previewHeight
            } else {
                height.toFloat() / previewWidth
            }

        /* Scale factor required to fit the preview to the SurfaceView size. */
        val finalScale = min(scaleX, scaleY)

        setScaleX(1 / scaleX * finalScale)
        setScaleY(1 / scaleY * finalScale)
    }
    setMeasuredDimension(width, height)
}

자바

@Override
void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);

    int relativeRotation = computeRelativeRotation(characteristics, surfaceRotationDegrees);

    if (previewWidth > 0f && previewHeight > 0f) {

        /* Scale factor required to scale the preview to its original size on the x-axis. */
        float scaleX = (relativeRotation % 180 == 0)
                       ? (float) width / previewWidth
                       : (float) width / previewHeight;

        /* Scale factor required to scale the preview to its original size on the y-axis. */
        float scaleY = (relativeRotation % 180 == 0)
                       ? (float) height / previewHeight
                       : (float) height / previewWidth;

        /* Scale factor required to fit the preview to the SurfaceView size. */
        float finalScale = Math.min(scaleX, scaleY);

        setScaleX(1 / scaleX * finalScale);
        setScaleY(1 / scaleY * finalScale);
    }
    setMeasuredDimension(width, height);
}

SurfaceView를 카메라 미리보기로 구현하는 방법에 관한 자세한 내용은 다음을 참고하세요. 카메라 방향.

TextureView

TextureView의 성능이 다음보다 낮습니다. SurfaceView와 더 많은 작업이지만 TextureView의 경우 최대의 이점이 있습니다. 컨트롤도 제어할 수 있습니다.

TextureView는 센서 방향에 따라 센서 이미지 버퍼를 회전하지만 기기 회전이나 미리보기 크기 조정을 처리하지 않습니다.

크기 조정 및 회전은 Matrix 변환. TextureView의 크기를 올바로 조정하고 회전합니다. 카메라 앱에서 크기 조절 가능한 노출 영역 지원

상대 회전

카메라 센서의 상대적 회전은 카메라에 잡히는 데 필요한 카메라 센서 출력을 기기 방향에 맞춥니다.

상대 회전은 SurfaceViewTextureView와 같은 구성요소에 사용됩니다. 를 사용하여 미리보기 이미지의 x 및 y 배율을 결정합니다. 또한 센서 이미지 버퍼의 회전을 지정합니다.

CameraCharacteristicsSurface 클래스를 사용하면 카메라 센서의 상대적 회전:

Kotlin

/**
 * Computes rotation required to transform the camera sensor output orientation to the
 * device's current orientation in degrees.
 *
 * @param characteristics The CameraCharacteristics to query for the sensor orientation.
 * @param surfaceRotationDegrees The current device orientation as a Surface constant.
 * @return Relative rotation of the camera sensor output.
 */
public fun computeRelativeRotation(
    characteristics: CameraCharacteristics,
    surfaceRotationDegrees: Int
): Int {
    val sensorOrientationDegrees =
        characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)!!

    // Reverse device orientation for back-facing cameras.
    val sign = if (characteristics.get(CameraCharacteristics.LENS_FACING) ==
        CameraCharacteristics.LENS_FACING_FRONT
    ) 1 else -1

    // Calculate desired orientation relative to camera orientation to make
    // the image upright relative to the device orientation.
    return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360
}

자바

/**
 * Computes rotation required to transform the camera sensor output orientation to the
 * device's current orientation in degrees.
 *
 * @param characteristics The CameraCharacteristics to query for the sensor orientation.
 * @param surfaceRotationDegrees The current device orientation as a Surface constant.
 * @return Relative rotation of the camera sensor output.
 */
public int computeRelativeRotation(
    CameraCharacteristics characteristics,
    int surfaceRotationDegrees
){
    Integer sensorOrientationDegrees =
        characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);

    // Reverse device orientation for back-facing cameras.
    int sign = characteristics.get(CameraCharacteristics.LENS_FACING) ==
        CameraCharacteristics.LENS_FACING_FRONT ? 1 : -1;

    // Calculate desired orientation relative to camera orientation to make
    // the image upright relative to the device orientation.
    return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360;
}

창 측정항목

카메라 크기를 결정하는 데 화면 크기를 사용해서는 안 됩니다. 뷰파인더 카메라 앱이 화면의 일부에서 실행 중일 수 있습니다. 휴대기기에서는 멀티 윈도우 모드, ChromeOS에서는 자유 모드로 작동합니다.

WindowManager#getCurrentWindowMetrics() (API 수준 30에 추가됨)은 변경할 수 있습니다. Jetpack WindowManager 라이브러리 메서드 WindowMetricsCalculator#computeCurrentWindowMetrics()WindowInfoTracker#currentWindowMetrics() API 수준 14와의 유사한 지원을 제공합니다.

180도 회전

기기를 180도 회전 (예: 자연스러운 방향에서 자연스러운 방향 거꾸로 되어 있음)는 onConfigurationChanged() 있습니다. 따라서 카메라 미리보기가 거꾸로 보이게 됩니다.

180도 회전을 감지하려면 DisplayListener 호출로 기기 회전을 확인합니다. Display#getRotation()onDisplayChanged() 있습니다.

독점 리소스

Android 10 이전에는 멀티 윈도우에서 최상단에 표시되는 활동만 환경이 RESUMED 상태였습니다. 이는 사용자에게 혼란을 주었고 시스템이 어떤 활동이 재개되었는지에 대한 표시를 제공하지 않았습니다.

Android 10 (API 수준 29)에는 표시되는 모든 활동이 발생하는 다중 재개가 도입되었습니다. RESUMED 상태입니다. 표시되는 활동이 PAUSED에 계속 들어갈 수 있습니다. 예를 들어 투명한 활동이 활동 위에 있거나 PIP 모드와 같이 활동에 포커스를 둘 수 없는 경우( PIP 모드 지원).

카메라, 마이크, 기타 독점 또는 기타 장치를 사용하는 API 수준 29 이상의 싱글톤 리소스는 다중 재개를 지원해야 합니다. 대상 예를 들어 재개된 활동 3개가 카메라를 사용하려는 경우 하나만 이 독점 리소스에 액세스할 수 있습니다. 각 활동은 onDisconnected() 더 높은 우선순위로 카메라에 대한 선점형 액세스를 인식하는 콜백 있습니다.

자세한 내용은 다중 재개.

추가 리소스

  • Camera2 샘플은 Camera2Basic 앱을 참고하세요. 를 참조하세요.
  • CameraX 미리보기 사용 사례에 관한 자세한 내용은 CameraX를 참고하세요. 미리보기를 구현합니다.
  • CameraX 카메라 미리보기 샘플 구현은 CameraXBasic 찾을 수 있습니다.
  • ChromeOS의 카메라 미리보기에 관한 자세한 내용은 다음을 참고하세요. 카메라 방향.
  • 폴더블 기기 개발에 관한 자세한 내용은 다음을 참고하세요. 폴더블 알아보기