이 문서는 Android SDK 0.0.9 기준입니다. API 이름과 동작은 iOS · Flutter 와 같습니다.
초기화
앱 시작 시 한 번 SDK 를 준비합니다.onDebugLog 는 initialize 보다 먼저 등록해야 초기화 로그를 놓치지 않습니다.
.initialize
콘솔에서 발급한 SDK 키(ock_sdk_…)로 SDK 를 초기화합니다. 키 검증과 설정 수신을 함께 하며, 앱이 넘기는 키는 이것 하나뿐입니다.
- 성공 후 다시 부르면 무시되고, 실패 후 다시 부르면 재시도합니다. 다른 키로 부르면 세션을 새로 구성합니다.
- 건물·층은 조회하지 않습니다. 기기 지원 여부도 여기서 막지 않습니다 — 미지원 기기도 초기화는 통과하며 측위 시작(
begin)에서만 거절됩니다. - 자체 서버를 쓰는 고객만
baseUrl을 넘깁니다. 기본값은https://console.ones1ght.com/api/sdk/v1입니다.
.requestPermission
측위 권한을 확인하고 필요하면 시스템 권한 창을 띄웁니다. 이미 답한 권한이면 창 없이 바로 돌아오며,initialize 전에도 부를 수 있습니다.
RANGING·정밀 위치·BLUETOOTH_SCAN을 한 번에 묻습니다.ComponentActivity를 넘깁니다.
.setLanguage
SDK 로그와 안내 문구의 언어를 정합니다 —"ko" · "ja" · "en". nil(null)이면 기기 언어를 따릅니다(기본값).
.onDebugLog
SDK 내부 활동 로그를 등급과 함께 받습니다. 등급은log < info < warn < error 이며, 코드가 붙은 줄([E3007] …)은
에러 코드로 찾아볼 수 있습니다. 수집 방법은 디버그 로그를 참고하세요.
LogLevel 은 Android 에서 co.onecheck.ones1ght.android.runtime.LogLevel 입니다.
.reset
세션을 버립니다. 이후 다른 키로initialize 할 수 있습니다 — 런타임에 키를 바꿀 때 씁니다.
상태 조회
네트워크를 쓰지 않고 SDK 상태를 읽습니다. Java 는 getter(OneS1ght.isInitialized(), OneS1ght.getDeviceAvailability())로 읽습니다.
.isInitialized
초기화가 성공했는지 — 키가 유효하고 설정을 받았는지 — 를 돌려줍니다..deviceAvailability
이 기기에서 측위가 되는지와 안 되는 이유를 돌려줍니다.isDeviceAvailable 은 그 요약(== available)입니다.
Kotlin·Java 는
AVAILABLE · OS_VERSION_TOO_LOW · DEVICE_NOT_SUPPORTED 입니다.
.googleMapKey
콘솔이 내려준 Google Maps 키입니다. 앱이 자체 지도를 그릴 때 씁니다.initialize 가 성공하기 전에는 비어 있습니다.
.sdkVersion
SDK 버전 문자열입니다.프로필
측위 데이터는 프로필 ID 로 묶입니다. 고객사 회원 ID 는 서버로 오지 않습니다 — 회원과 프로필의 매핑은 고객사만 보관합니다..createProfile
속성을 담아 프로필을 만들고 서버가 발급한profileId 를 돌려받습니다. 앱이 보관해 두고 다음 실행에도 재사용하세요.
속성은 자유롭게 정할 수 있으며, 나이는 정확한 값 대신 연령대("20s")를 권장합니다.
.identify
이 기기의 측위를 프로필에 연결합니다. 측위를 시작하기 전에 반드시 호출하세요 — 없으면begin 이 E1004 로 거절됩니다.
로그아웃할 때는 nil(null)을 넘깁니다. initialize 앞뒤 어디서 불러도 되고, reset·키 교체 뒤에도 이어집니다.
.fetchProfile
프로필 속성을 조회합니다..replaceProfile
프로필 속성을 통째로 교체합니다. 넘기지 않은 속성은 지워집니다 — 부분 갱신이 아닙니다..deleteProfile
프로필을 삭제합니다. 이미 쌓인 좌표·이벤트는 보존 정책을 따릅니다.공간 조회
콘솔에 등록된 건물·층·구역을 읽습니다. 서버 엔드포인트 하나당 메서드 하나이며, 목록과 단건이 짝을 이룹니다..buildings
건물 목록을 돌려줍니다. 콘솔에 연결된 공간이 없으면 빈 목록입니다.building(id:) 는 건물 하나를 돌려줍니다.
.floors
건물의 층 목록입니다. 목록을 가볍게 유지하려고 도면 이미지는 비워서 줍니다(image == nil).
.floor
층 하나를 도면 이미지와 함께 돌려줍니다. 캐시에서 나오므로 요청이 늘지 않고, 콘솔이 도면을 바꾸면 캐시를 버립니다. 좌표는 도면 로컬 미터이며originX · originY · widthM · heightM 으로 화면 좌표로 바꿉니다.
.zones
층의 구역 목록입니다.zone(buildingId:floorId:zoneId:) 는 구역 하나를 돌려줍니다.
.locators
층에 설치된 로케이터 배치와 UWB 세션 ID 입니다. 설치·점검 화면처럼 로케이터를 직접 그릴 때 씁니다.층 지정
층 지정은 선택입니다 — 측위 엔진이 BLE 로 층을 스스로 찾고, 찾은 층은onFloorDetected 로 알려 줍니다. 사람이 층을 고르거나 측위 전에 지도를 먼저 그릴 때 setFloorMap 을 씁니다.
.setFloorMap
층을 지정합니다. 로케이터·세션·구역을 측위 엔진에 넣고, 측위 중이면 세션을 유지한 채 즉시 층을 바꿉니다.nil(null)을 넘기면 지정을 비웁니다.
buildingId를 생략하면 직전에 지정한 건물을 씁니다. 처음 지정할 때는 건물을 함께 넘기세요 — 건물 인자도 직전 건물도 없으면E3001로 거절되고 지금 층은 그대로 둡니다.- 층을 지정하지 않아도 좌표는 나오지만, 구역 이벤트(진입·이탈·체류)를 받으려면 층을 지정해야 합니다.
.refreshZones
현재 층의 구역만 다시 받아 판정에 바로 반영합니다. 도면은 다시 받지 않아 가볍습니다. 실패해도 던지지 않고 지금 가진 구역을 돌려줍니다. 콘솔에서 구역이 바뀌었다는 신호(onConfigChanged)를 받았을 때 씁니다.
측위 세션
측위는FloorSession 하나로 다룹니다. UWB 라디오·판정 엔진·좌표 버퍼가 기기당 하나뿐이라 세션은 항상 같은 인스턴스입니다.
.floorSession
측위 세션을 가져옵니다.initialize 를 한 번도 부르지 않았으면 E1001 입니다.
.begin
측위를 시작합니다. 매장에 들어왔을 때 부르세요. 거절되면 오류를 던집니다 —E1001(초기화 안 함) · E1004(identify 안 함) · E2001(OS 낮음) · E2002(미지원 기기).
.end
측위를 멈추고 남은 좌표를 전송합니다. 초기화와 층 지정은 유지되므로begin 으로 다시 시작할 수 있습니다.
.pause · .resume
일시정지 — 좌표 표시·전송·구역 판정만 멈추고 엔진은 계속 돌립니다. 층을 계속 잡고 있어서resume 하면 바로 이어집니다.
일시정지는 백그라운드에 다녀와도 유지되고 resume · end · begin 에서만 풀립니다.
.isRunning · .isPaused
측위 가동 여부와 일시정지 여부입니다. 엔진을 다시 켜지 못해 SDK 가 세션을 닫으면isRunning 이 false 가 됩니다. 지금 지정된 층은 session.floor 로 읽습니다.
세션 이벤트
이벤트는 세션에 답니다. 모든 콜백은 메인 스레드에서 불리므로 UI 를 바로 고쳐도 됩니다..onPosition
실시간 좌표입니다 — 도면 로컬 미터(x · y · z), 최대 초당 4회.
.onZoneEnter · .onZoneExit
구역 진입·이탈입니다. 기기에서 바로 판정하므로 서버를 거치지 않고 즉시 옵니다. 앱이 백그라운드로 내려가면 안에 있던 구역의 이탈도 옵니다(일시정지 중 제외)..onZoneDwell
구역에 머문 시간이 그 구역의dwellSeconds 에 닿으면 방문당 한 번 옵니다 — (구역, 체류 초). dwellSeconds 가 없는 구역은 오지 않습니다.
.onTriggers
구역 이벤트에 대해 서버가 매칭한 개인화 액션입니다 — (구역 ID, 트리거 목록).type 은 signage · coupon · tracking · merch · generic 이며 값이 늘 수 있습니다.
.onFloorDetected
측위 엔진이 층을 잡으면 층 ID(Floor.id 와 같은 값)를, 잃으면 nil(null)을 줍니다. 그 층으로 setFloorMap 하면 구역 이벤트까지 받을 수 있습니다.
.onStopped
세션이 닫혔을 때 이유와 함께 옵니다. 불릴 때isRunning 은 이미 false 입니다.
엔진이 스스로 꺼지면 SDK 가 3·10·30초 뒤 다시 켜 봅니다(앱이 화면에 있을 때만). 그래도 안 되거나 권한·Bluetooth·라이선스처럼 사람이 풀어야 하는 원인이면 세션을 닫습니다 — 원인을 푼 뒤
begin 으로 다시 여세요. Kotlin·Java 는 ENDED · ENGINE_FAILED 입니다.
.onConfigChanged
콘솔에서 구역·도면·시책이 바뀌면 알려 줍니다. SDK 는 이 신호로 아무것도 하지 않습니다 — 무엇을 다시 받을지는 앱이 정합니다.
Kotlin·Java 는
ZonesChanged · PlanChanged · RulesChanged · SdkConfigChanged · ResyncNeeded 클래스입니다.
데이터 전송
좌표는 300건 또는 60초 중 먼저 닿는 쪽에서 자동으로 전송됩니다. 백그라운드로 갈 때와end() 때도 남은 좌표를 보냅니다. 전송에 실패한 좌표는 다음 주기 전송이 다시 보냅니다.
.uploadPendingPositions
쌓인 좌표를 지금 바로 전송합니다..discardPendingPositions
쌓인 좌표를 보내지 않고 버립니다. 전송 중에 불러도 안전합니다.오류 처리
오류 받기
실패는 SDK 상태 오류(SdkError)와 통신 오류(ApiError) 둘로 옵니다. 어느 쪽이든 에러 코드 문자열(E1002 등)을 꺼낼 수 있고, 코드는 iOS·Android·Flutter 가 같습니다.
ApiError 는 Android 에서 co.onecheck.ones1ght.android.network.ApiError 입니다.
표의 이름은 Swift 기준입니다. Kotlin·Java 는 첫 글자가 대문자입니다(
SdkError.NotInitialized, E3001 은 SdkError.BuildingNotSet).
측위 중 문제(E4001E4004), 공간 설정 문제(E3002E3009), 권한·Bluetooth(E2003 · E2004)는 던지지 않고 로그로만 남습니다 — onDebugLog 나 콘솔 로그 분석기에서 확인하세요.
모델
필드 이름은 세 플랫폼이 같습니다. 목록은List<T>, 바이트는 ByteArray 입니다.
Coordinates
Building · Floor
Locator · FloorLocators
Zone
콘솔 구역은 지도 표시·구역 ID 매핑·서버 전송에만 쓰입니다(설정 방법). 측위 엔진이 알려 주는 영역 이름과 콘솔 구역 이름이 같아야 이벤트가 이어지며, 같은 이름이 없으면
E3009(WARN)가 한 번 남고 그 영역의 이벤트는 서버로 가지 않습니다.
Trigger
SDK 의 열거형(
ConfigChange · StopReason · PermissionStatus · DeviceAvailability · LogLevel · 오류 코드)은 마이너 버전에서 값이 늘 수 있습니다. Kotlin when 에는 else 를 두세요.커스텀 측위 provider
session.begin(provider) 에 직접 만든 측위 provider 를 넣을 수 있습니다. 보통은 쓸 일이 없습니다 —
인자 없는 begin() 이 내장 provider 를 씁니다. 필수는 delegate · start() · stop() 셋이고 나머지는 기본 구현이 있습니다.
onPosition · onZoneEnter/Exit/Dwell · onFloorDetected · onStopped)이 내장 provider 와 같은 길로 옵니다.
co.onecheck.ones1ght.android.positioning 패키지에 있습니다. 테스트용 provider 가 필요하면 이 인터페이스를 직접 구현하세요.
UwbPositioningProvider
0.0.5 부터. 설치·점검 앱이나 직접 그리는 지도처럼 엔진 상태(엔진 단계 · 탐지한 층 · 좌표 수 · 로그)를
직접 봐야 할 때만 앱이 만들어
session.begin(provider) 에 넣습니다. 넣어도 begin() 과 똑같이 다뤄집니다 — 같은 기기 확인,
구역 이벤트는 세션 콜백으로, 엔진 로그는 OneS1ght.onDebugLog 로 갑니다.
상태는 게터와
StateFlow(…Flow) 둘 다로 읽습니다. Kotlin 은 …Flow 를 모으고, Java 는 게터와 setOnChange(…) 를 씁니다.
측위 엔진은 로케이터별 수신 상태를 알려 주지 않습니다. 그래서 좌표가 있으면
received · matched 가 등록된 로케이터 전부,
없으면 빈 목록이고 missing 은 항상 비어 있습니다 — 로케이터 한 대가 꺼졌는지는 이 값으로 가릴 수 없습니다.바뀐 이름
Android 0.0.7 에서 iOS 와 이름을 맞췄습니다. 옛 이름은 deprecated 로 남아 경고만 내고 그대로 동작하며, Android Studio 의 Replace with … 가 새 이름으로 바꿔 줍니다.
자세한 내용은 릴리스 노트를 참고하세요.
스레딩
suspendAPI 는 어느 코루틴에서 불러도 됩니다.identify·discardPendingPositions·pause·resume은 메인 스레드에서 부르세요.- 콜백과 Java
Callback결과는 모두 메인 스레드로 옵니다 — UI 를 바로 고쳐도 됩니다.
알아둘 제약
실제 측위는 시뮬레이터·에뮬레이터에서 확인할 수 없습니다. UWB 를 지원하는 실기기에서 테스트하세요.