Petnow LogoPetnow
Android SDKUI 모듈

UI 모듈 개요

Petnow Android UI 모듈의 구조와 핵심 컴포넌트 설명.


Petnow UI 모듈이란?

Petnow UI 모듈은 반려동물 생체 데이터 캡처를 위한 즉시 사용 가능한 카메라 UI를 제공하는 모듈입니다. 복잡한 카메라 설정, 탐지 로직, 이미지 처리 등을 모두 처리하여 개발자는 몇 줄의 코드만으로 전문적인 생체 인식 기능을 앱에 통합할 수 있습니다.

UI Module Intro

핵심 가치

  • 🚀 빠른 통합: 복잡한 Camera2 API를 알 필요 없음
  • 🎯 실시간 가이드: 사용자에게 최적의 촬영 방법 안내
  • 🎨 커스터마이즈 가능: 앱의 디자인에 맞게 조정 가능
  • 📱 Fragment 기반: 기존 Android 앱에 쉽게 통합
  • 🔧 Helper 지원: Fragment 없이도 사용 가능 (Compose, React Native 등)

아키텍처

Petnow UI 모듈은 복잡한 상태관리와 ML 프레임워크 연동 로직을 숨기고, 개발자에게 간단한 인터페이스만 제공합니다.

핵심 컴포넌트

PetnowCameraFragment

Android Fragment로 카메라 프리뷰와 탐지 오버레이를 표시합니다.

Camera Preview실시간 카메라 영상렌더링 레이어
Detection Overlay탐지 박스, 가이드상태 시각화Custom UI개발자 커스텀오버레이 UI

역할:

  • 카메라 프리뷰 렌더링
  • 탐지 오버레이 표시
  • 사용자 상호작용 처리
  • 카메라 권한 자동 요청
  • 내부적으로 탐지 상태 및 진행률 관리

간단한 사용 예시:

import android.content.Context
import io.petnow.ui.PetnowCameraFragment
import io.petnow.callback.PetnowCameraDetectionListener

class CustomCameraFragment : PetnowCameraFragment(), PetnowCameraDetectionListener {

    override fun provideCustomOverlayLayout(): Int? = R.layout.fragment_custom_camera

    override fun onAttach(context: Context) {
        super.onAttach(context)
        setPetnowCameraDetectionListener(this)
    }
    
    override fun onDetectionStatus(primaryDetectionStatus: PetnowDetectionStatus) {
        // 탐지 상태 업데이트
    }
    
    override fun onDetectionProgress(progress: Int) {
        // 진행률 업데이트 (0-100)
    }
    
    override fun onDetectionFinished(result: DetectionCaptureResult) {
        // 촬영 완료 처리
    }
}

참고: PetnowCameraFragment가 모든 카메라 로직을 처리하므로, 개발자는 listener 메서드만 구현하면 됩니다.

PetnowCameraHelper

Fragment 상속 없이 사용할 수 있는 UI 독립적인 카메라 컨트롤러입니다.

역할:

  • ObjectDetector 라이프사이클 관리
  • 탐지 상태를 StateFlow로 제공
  • PetnowCameraDetectionListener 콜백 전달
  • 카메라 프리뷰/오버레이 등 UI는 개발자가 직접 구현

적합한 사용 사례:

  • Jetpack Compose 기반 앱
  • React Native / Flutter 브릿지
  • 완전 커스텀 카메라 UI
val helper = PetnowCameraHelper(context, coroutineScope)
helper.initialize()
helper.initializeDetector()
helper.setDetectionListener(listener)

// StateFlow로 상태 관찰
helper.state.collect { state -> /* UI 업데이트 */ }

참고: 자세한 사용법은 PetnowCameraHelper 사용법을 참고하세요.

세션 개념

촬영 과정은 두 가지 세션으로 관리됩니다:

Capture Session (캡처 세션)

  • 서버에서 Petnow Server API(createCaptureSession)를 호출하여 생성
  • 서버에서 받은 captureSessionId를 클라이언트로 전달하여 Fragment arguments에 설정
  • 하나의 Capture Session은 여러 Detection Session을 포함할 수 있음
  • Petify Console에서 전체 촬영 과정을 추적하고 메트릭 분석에 활용

Detection Session (탐지 세션)

  • 실제 탐지를 시작한 시점부터 탐지가 완료되거나 실패할 때까지의 세션
  • 사용자가 재촬영하면 새로운 Detection Session이 시작됨

captureSessionId 전달 방법

import io.petnow.ui.PetnowCameraFragment
import java.util.UUID

class MyCameraFragment : PetnowCameraFragment() {
    companion object {
        fun newInstance(captureSessionId: UUID) = MyCameraFragment().apply {
            arguments = Bundle().apply {
                putString(ARG_CAPTURE_SESSION_ID, captureSessionId.toString())
            }
        }
    }
}

// 사용 예시
lifecycleScope.launch {
    // 서버에서 captureSessionId를 받아옵니다
    // (서버는 Petnow Server API의 createCaptureSession을 호출)
    val captureSessionId: UUID = yourServerApi.createCaptureSession(
        species = "DOG",
        purpose = "PET_PROFILE_REGISTRATION"
    )
    
    // Fragment 생성 및 이동
    val fragment = MyCameraFragment.newInstance(captureSessionId)
    // ... navigation
}

참고: 재촬영 시 새로운 Detection Session이 시작됩니다. Petify Console에서 각 세션을 개별적으로 추적할 수 있습니다.

상태 관리

PetnowDetectionStatus

카메라 프레임의 탐지 결과 상태를 나타냅니다.

import io.petnow.ui.status.PetnowDetectionStatus

enum class PetnowDetectionStatus {
    Error,              // 오류 발생
    TooBright,          // 너무 밝음
    TooDark,            // 너무 어두움
    NoObject,           // 대상 미탐지
    TooFarAway,         // 너무 멀리 있음
    TooClose,           // 너무 가까이 있음
    NoseNotFound,       // 코를 찾을 수 없음
    NotFrontFace,       // 정면이 아님
    NotFrontCatFaceHor, // 고양이 얼굴 수평 정렬 필요
    NotFrontCatFaceTop, // 고양이 얼굴 위쪽 정렬 필요
    NotFrontCatFaceBottom, // 고양이 얼굴 아래쪽 정렬 필요
    TooBlurred,         // 너무 흐림
    ShadowDetected,     // 그림자 감지됨
    GlareDetected,      // 눈부심 감지됨
    MotionBlurDetected, // 모션 블러 감지됨
    DefocusedBlurDetected, // 초점 흐림 감지됨
    NotFrontNose,       // 코가 정면이 아님
    FurDetected,        // 털이 감지됨
    FakeDetected,       // 가짜 감지됨
    Detected            // 탐지 완료
}

DetectionCaptureResult

최종 촬영 결과입니다.

import io.petnow.ui.DetectionCaptureResult

sealed class DetectionCaptureResult {
    data class Success(
        val noseImageFiles: List<File>,  // 코무늬 이미지
        val faceImageFiles: List<File>   // 얼굴 이미지
    ) : DetectionCaptureResult()

    data object Fail : DetectionCaptureResult()
}

데이터 흐름

핵심 포인트: PetnowCameraFragment를 상속하고 PetnowCameraDetectionListener를 구현하면, Fragment가 자동으로 모든 카메라 로직을 처리하고 필요한 이벤트만 콜백으로 전달합니다.

데이터 흐름 설명

1. 실시간 상태 업데이트

  • PetnowCameraDetectionListener를 통해 다음 이벤트를 수신합니다:
    • onDetectionStatus(status): 현재 프레임의 탐지 상태 (PetnowDetectionStatus)
    • onDetectionProgress(progress): 탐지 진행률 (0 ~ 100)
  • 커스텀 UI에서 이 값들을 활용하여 실시간으로 화면을 업데이트합니다.

2. 최종 결과 전달

  • 탐지가 완료되면 PetnowCameraFragment가 이미지를 저장하고 DetectionCaptureResult를 생성합니다.
  • onDetectionFinished(result) 콜백으로 결과가 전달됩니다.
    • DetectionCaptureResult.Success - 촬영 성공 (이미지 파일 리스트 포함)
    • DetectionCaptureResult.Fail - 촬영 실패

다음 단계

UI 모듈의 구조를 이해했다면 다음 문서를 참고하세요:

참고 자료

On this page