> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ones1ght.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Android SDK

> SDK Version 0.0.9

## 패키지 선언

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  import co.onecheck.ones1ght.android.*           // OneS1ght · FloorSession · SdkError · 리스너
  import co.onecheck.ones1ght.android.model.*     // Building · Floor · Zone · Coordinates · Trigger · ConfigChange
  ```

  ```java Java icon="java" theme={null}
  import co.onecheck.ones1ght.android.*;          // OneS1ght · FloorSession · SdkError · Callback · 리스너
  import co.onecheck.ones1ght.android.model.*;    // Building · Floor · Zone · Coordinates · Trigger · ConfigChange
  ```
</CodeGroup>

## 초기화

### .initialize

OneS1ght API 키로 측위엔진을 초기화합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  OneS1ght.initialize(context = context.applicationContext, sdkKey = "YOUR_SDK_KEY")
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.initialize(context, "YOUR_SDK_KEY", new Callback<Void>() {
      @Override public void onSuccess(Void result) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .requestPermission

측위엔진 사용을 위한 앱 권한을 요청합니다.

| 결과 | 뜻 |
| - | - |
| `AUTHORIZED` | 측위 가능 |
| `DENIED` | 권한 거부됨 |
| `UNSUPPORTED` | 측위 미지원 기기 |

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val status = OneS1ght.requestPermission(activity)
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.requestPermission(activity, new Callback<PermissionStatus>() {
      @Override public void onSuccess(PermissionStatus status) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .setLanguage

SDK 로그 문구 언어를 설정합니다.<br />
`ko` : 한국어,  `ja` : 일본어,  `en` : 영어, `null` : 시스템 설정 언어

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  OneS1ght.setLanguage("ko")
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.setLanguage("ko");
  ```
</CodeGroup>

### .onDebugLog

SDK 로그를 수신합니다.<br />
`ko` : 로그 레벨, `message` : 로그 메세지

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  OneS1ght.onDebugLog = DebugLogListener { level, message ->
      if (level >= LogLevel.WARN) Log.w("OneS1ght", message)
  }
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.setOnDebugLog((level, message) -> {
      if (level.compareTo(LogLevel.WARN) >= 0) Log.w("OneS1ght", message);
  });
  ```
</CodeGroup>

### .reset

로케이터의 세션을 초기화합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  OneS1ght.reset()
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.reset(new Callback<Void>() {
      @Override public void onSuccess(Void result) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

## 상태 조회

### .isInitialized

초기화 성공 확인 여부를 반환합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val ready = OneS1ght.isInitialized
  ```

  ```java Java icon="java" theme={null}
  boolean ready = OneS1ght.isInitialized();
  ```
</CodeGroup>

### .deviceAvailability

측위 가능 기기를 판별하고 미지원시 사유를 반환합니다.

| 값 | 뜻 |
| - | - |
| `AVAILABLE` | 측위 가능 |
| `OS_VERSION_TOO_LOW` | Android 17(API 37) 미만 |
| `DEVICE_NOT_SUPPORTED` | UWB 미지원 기기 |

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  when (OneS1ght.deviceAvailability) {
      DeviceAvailability.AVAILABLE            -> Unit
      DeviceAvailability.OS_VERSION_TOO_LOW   -> Unit
      DeviceAvailability.DEVICE_NOT_SUPPORTED -> Unit
      else                                    -> Unit
  }
  ```

  ```java Java icon="java" theme={null}
  DeviceAvailability availability = OneS1ght.getDeviceAvailability();
  boolean available = OneS1ght.isDeviceAvailable();
  ```
</CodeGroup>

### .googleMapKey

도면을 표시할 Google Maps API 키를 반환합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val mapKey = OneS1ght.googleMapKey   // String?
  ```

  ```java Java icon="java" theme={null}
  String mapKey = OneS1ght.getGoogleMapKey();
  ```
</CodeGroup>

### .SDK\_VERSION

사용중인 SDK 버전을 반환합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val version = OneS1ght.SDK_VERSION   // "0.0.9"
  ```

  ```java Java icon="java" theme={null}
  String version = OneS1ght.SDK_VERSION;
  ```
</CodeGroup>

## 프로필

### .createProfile

새로운 개인화 프로필을 생성합니다. 성공적으로 생성하면 고유 프로필 ID를 반환합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val profileId = OneS1ght.createProfile(mapOf("gender" to "F", "ageBand" to "20s"))
  ```

  ```java Java icon="java" theme={null}
  Map<String, String> attributes = new HashMap<>();
  attributes.put("gender", "F");
  attributes.put("ageBand", "20s");
  OneS1ght.createProfile(attributes, new Callback<String>() {
      @Override public void onSuccess(String profileId) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .identify

수집할 측위 데이터를 묶을 프로필을 연결합니다. 연결 해제시 `null`으로 설정하세요.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  OneS1ght.identify(profileId)
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.identify(profileId);
  ```
</CodeGroup>

### .fetchProfile

프로필의 속성을 조회합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val attributes = OneS1ght.fetchProfile(profileId)
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.fetchProfile(profileId, new Callback<Map<String, String>>() {
      @Override public void onSuccess(Map<String, String> attributes) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .replaceProfile

프로필 속성을 교체하며 이전 데이터는 삭제됩니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  OneS1ght.replaceProfile(profileId, mapOf("gender" to "F", "ageBand" to "30s"))
  ```

  ```java Java icon="java" theme={null}
  Map<String, String> attributes = new HashMap<>();
  attributes.put("gender", "F");
  attributes.put("ageBand", "30s");
  OneS1ght.replaceProfile(profileId, attributes, new Callback<Void>() {
      @Override public void onSuccess(Void result) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .deleteProfile

프로필 정보를 영구 삭제합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  OneS1ght.deleteProfile(profileId)
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.deleteProfile(profileId, new Callback<Void>() {
      @Override public void onSuccess(Void result) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

## 공간 조회

### .buildings

테넌트와 연관된 모든 건물 목록을 조회합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val buildings = OneS1ght.buildings()
  val building = OneS1ght.building(id = buildingId)
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.buildings(new Callback<List<Building>>() {
      @Override public void onSuccess(List<Building> buildings) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .floors

건물의 층 목록을 조회합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val floors = OneS1ght.floors(buildingId)
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.floors(buildingId, new Callback<List<Floor>>() {
      @Override public void onSuccess(List<Floor> floors) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .floor

선택한 층의 상세 정보를 조회합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val floor = OneS1ght.floor(buildingId, floorId)
  val png = floor.image   // ByteArray?
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.floor(buildingId, floorId, new Callback<Floor>() {
      @Override public void onSuccess(Floor floor) { byte[] png = floor.getImage(); }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .zones

선택한 층의 모든 구역을 조회합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val zones = OneS1ght.zones(buildingId, floorId)
  val zone = OneS1ght.zone(buildingId, floorId, zoneId)
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.zones(buildingId, floorId, new Callback<List<Zone>>() {
      @Override public void onSuccess(List<Zone> zones) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .locators

선택한 층의 로케이터 정보를 조회합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val floorLocators = OneS1ght.locators(buildingId, floorId)
  val ready = floorLocators.positioningReady
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.locators(buildingId, floorId, new Callback<FloorLocators>() {
      @Override public void onSuccess(FloorLocators floorLocators) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

## 층 지정

### .setFloorMap

측위를 시작할 층을 지정합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val floor = OneS1ght.floor(buildingId, floorId)
  OneS1ght.setFloorMap(floor, buildingId)
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.floor(buildingId, floorId, new Callback<Floor>() {
      @Override public void onSuccess(Floor floor) {
          OneS1ght.setFloorMap(floor, buildingId, new Callback<Void>() {
              @Override public void onSuccess(Void result) { }
              @Override public void onError(Throwable error) { }
          });
      }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .refreshZones

최신화된 구역 정보를 조회합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val zones = OneS1ght.refreshZones()
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.refreshZones(new Callback<List<Zone>>() {
      @Override public void onSuccess(List<Zone> zones) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

## 측위 세션

### .floorSession

선택한 층의 로케이터 세션을 획득합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val session = OneS1ght.floorSession()
  ```

  ```java Java icon="java" theme={null}
  FloorSession session = OneS1ght.floorSession();
  ```
</CodeGroup>

### .begin

사용자 측위를 시작합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  session.begin()
  ```

  ```java Java icon="java" theme={null}
  session.begin(new Callback<Void>() {
      @Override public void onSuccess(Void result) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .end

사용자 측위를 종료합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  session.end()
  ```

  ```java Java icon="java" theme={null}
  session.end(new Callback<Void>() {
      @Override public void onSuccess(Void result) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .pause · .resume

사용자 측위를 중지, 재개합니다. 종료와 달리 SDK 내 측위 엔진은 종료하지 않습니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  session.pause()
  session.resume()
  ```

  ```java Java icon="java" theme={null}
  session.pause();
  session.resume();
  ```
</CodeGroup>

### .isRunning · .isPaused

측위 상태여부와 중지여부를 반환합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  val running = session.isRunning
  val paused = session.isPaused
  val current = session.floor   // Floor?
  ```

  ```java Java icon="java" theme={null}
  boolean running = session.isRunning();
  boolean paused = session.isPaused();
  Floor current = session.getFloor();
  ```
</CodeGroup>

## 세션 이벤트

### .onPosition

실시간으로 사용자 좌표 반환 이벤트를 발생합니다. (기본값 1초당 4회)

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  session.onPosition = PositionListener { coordinates -> Log.d("OneS1ght", "${coordinates.x}, ${coordinates.y}") }
  ```

  ```java Java icon="java" theme={null}
  session.setOnPosition(coordinates -> Log.d("OneS1ght", coordinates.getX() + ", " + coordinates.getY()));
  ```
</CodeGroup>

### .onZoneEnter · .onZoneExit

구역 진입, 이탈시 이벤트가 동작합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  session.onZoneEnter = ZoneListener { zone -> Log.d("OneS1ght", "IN ${zone.name}") }
  session.onZoneExit  = ZoneListener { zone -> Log.d("OneS1ght", "OUT ${zone.name}") }
  ```

  ```java Java icon="java" theme={null}
  session.setOnZoneEnter(zone -> Log.d("OneS1ght", "IN " + zone.getName()));
  session.setOnZoneExit(zone -> Log.d("OneS1ght", "OUT " + zone.getName()));
  ```
</CodeGroup>

### .onZoneDwell

특정 구역의 체류 시간이 초과할 경우(`dwellSeconds` 기준) 이벤트가 발생합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  session.onZoneDwell = DwellListener { zone, seconds -> Log.d("OneS1ght", "DWELL ${zone.name} ${seconds}s") }
  ```

  ```java Java icon="java" theme={null}
  session.setOnZoneDwell((zone, seconds) -> Log.d("OneS1ght", "DWELL " + zone.getName() + " " + seconds));
  ```
</CodeGroup>

### .onTriggers

공간 내 이벤트(또는 시책) 동작시 이벤트가 발생합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  session.onTriggers = TriggersListener { zoneId, triggers ->
      triggers.forEach { trigger -> Log.d("OneS1ght", "${trigger.type} ${trigger.payload}") }
  }
  ```

  ```java Java icon="java" theme={null}
  session.setOnTriggers((zoneId, triggers) -> {
      for (Trigger trigger : triggers) Log.d("OneS1ght", trigger.getType());
  });
  ```
</CodeGroup>

### .onFloorDetected

로케이터의 BLE 신호를 수신한 경우 이벤트가 발생합니다.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  session.onFloorDetected = SessionFloorListener { floorId ->
      if (floorId == null) return@SessionFloorListener
      lifecycleScope.launch {
          val floor = OneS1ght.floor(buildingId, floorId)
          OneS1ght.setFloorMap(floor, buildingId)
      }
  }
  ```

  ```java Java icon="java" theme={null}
  session.setOnFloorDetected(floorId -> {
      if (floorId == null) return;
      OneS1ght.floor(buildingId, floorId, new Callback<Floor>() {
          @Override public void onSuccess(Floor floor) {
              OneS1ght.setFloorMap(floor, buildingId, new Callback<Void>() {
                  @Override public void onSuccess(Void result) { }
                  @Override public void onError(Throwable error) { }
              });
          }
          @Override public void onError(Throwable error) { }
      });
  });
  ```
</CodeGroup>

### .onStopped

사용자 측위가 중지된 경우 이벤트가 발생합니다.

| 이유 | 뜻 |
| - | - |
| `ENDED` | `end()` · `reset` · 키 교체 |
| `ENGINE_FAILED` | 측위엔진 구동 실패시 |

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  session.onStopped = SessionStoppedListener { reason ->
      when (reason) {
          FloorSession.StopReason.ENDED         -> Unit
          FloorSession.StopReason.ENGINE_FAILED -> Unit
          else                                  -> Unit
      }
  }
  ```

  ```java Java icon="java" theme={null}
  session.setOnStopped(reason -> {
      if (reason == FloorSession.StopReason.ENGINE_FAILED) { }
  });
  ```
</CodeGroup>

### .onConfigChanged

콘솔 페이지에서 설정이 변경되었을 경우 이벤트가 발생합니다.

| 신호 | 의미 |
| - | - |
| `ZonesChanged(floorId)` | 구역 변경 |
| `PlanChanged(floorId)` | 도면 변경 |
| `RulesChanged(zoneId)` | 시책 변경 |
| `SdkConfigChanged` | 원격 설정 변경 |
| `ResyncNeeded` | 재연결 · 이벤트 누락 |

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  session.onConfigChanged = ConfigChangeListener { change ->
      when (change) {
          is ConfigChange.ZonesChanged, is ConfigChange.ResyncNeeded -> lifecycleScope.launch { OneS1ght.refreshZones() }
          is ConfigChange.PlanChanged -> redrawFloor()
          else -> Unit
      }
  }
  ```

  ```java Java icon="java" theme={null}
  session.setOnConfigChanged(change -> {
      if (change instanceof ConfigChange.ZonesChanged || change instanceof ConfigChange.ResyncNeeded) {
          OneS1ght.refreshZones(new Callback<List<Zone>>() {
              @Override public void onSuccess(List<Zone> zones) { }
              @Override public void onError(Throwable error) { }
          });
      }
  });
  ```
</CodeGroup>

## 데이터 전송

좌표는 300건 또는 60초마다, 그리고 백그라운드 진입과 `end()` 때 자동 전송됩니다.

### .uploadPendingPositions

쌓인 좌표 즉시 전송.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  OneS1ght.uploadPendingPositions()
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.uploadPendingPositions(new Callback<Void>() {
      @Override public void onSuccess(Void result) { }
      @Override public void onError(Throwable error) { }
  });
  ```
</CodeGroup>

### .discardPendingPositions

쌓인 좌표 폐기.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  OneS1ght.discardPendingPositions()
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.discardPendingPositions();
  ```
</CodeGroup>

## 오류 처리

실패는 `SdkError`(SDK 상태) 와 `ApiError`(통신, `co.onecheck.ones1ght.android.network.ApiError`) 를 반환하며, 자세한 내용은 [에러 코드](/sdk/troubleshooting/error-codes)를 참고하세요.

<CodeGroup>
  ```kotlin Kotlin icon="https://mintcdn.com/onecheck/wv66PbaB8dD4xd9I/images/icons/kotlin.svg?fit=max&auto=format&n=wv66PbaB8dD4xd9I&q=85&s=3721cc48a6f44aef50ea7a0151e369f2" theme={null}
  try {
      OneS1ght.initialize(context = context.applicationContext, sdkKey = key)
  } catch (e: SdkError) {
      Log.w("OneS1ght", e.code.code)                     // "E1003"
  } catch (e: ApiError) {
      Log.w("OneS1ght", "${e.code.code} ${e.message}")   // "E5005 …"
  }
  ```

  ```java Java icon="java" theme={null}
  OneS1ght.initialize(context, key, new Callback<Void>() {
      @Override public void onSuccess(Void result) { }
      @Override public void onError(Throwable error) {
          if (error instanceof SdkError) {
              Log.w("OneS1ght", ((SdkError) error).getCode().getCode());   // "E1003"
          } else if (error instanceof ApiError) {
              Log.w("OneS1ght", ((ApiError) error).getCode().getCode() + " " + error.getMessage());
          }
      }
  });
  ```
</CodeGroup>

## 모델

목록은 `List<T>`, 바이트는 `ByteArray` 입니다.

### Coordinates

| 필드 | 타입 | 설명 |
| - | - | - |
| `x` · `y` | `Double` | 도면 로컬 미터 |
| `z` | `Double` | 높이 |

### Building · Floor

| 타입 | 필드 | 설명 |
| - | - | - |
| `Building` | `id` · `name` | 건물 ID · 이름 |
| | `floorCount: Int?` | 층 수 |
| `Floor` | `id` · `name` | 층 ID · 이름 |
| | `image: ByteArray?` | 도면 이미지 (BASE64) |
| | `hasPlan: Boolean` | 도면 등록 여부 |
| | `originX` · `originY` | 도면 원점(미터) |
| | `widthM` · `heightM` | 도면 크기(미터) |
| | `minX` · `minY` · `maxX` · `maxY` | 배치 범위 |

### Locator · FloorLocators

| 타입 | 필드 | 설명 |
| - | - | - |
| `Locator` | `address: Int` | UWB MAC 뒤 2바이트 |
| | `x` · `y` · `z` | 도면 로컬 미터 |
| `FloorLocators` | `locators` | 층의 로케이터 목록 |
| | `sessionId: Int?` | UWB 세션 — 층마다 다름 |
| | `positioningReady: Boolean` | 로케이터와 세션이 모두 있는가 |

### Zone

| 필드 | 타입 | 설명 |
| - | - | - |
| `id` · `name` | `String` | 구역 ID · 이름 |
| `polygon` | `List<Position>` | 꼭짓점(`x`, `y` 미터) |
| `dwellSeconds` | `Int?` | 체류 이벤트 기준(초) |
| ㅇㅇ | | |

### Trigger

| 필드 | 타입 | 설명 |
| - | - | - |
| `triggerId` | `String` | 트리거 ID |
| `type` | `String` | `signage` · `coupon` · `tracking` · `merch` · `generic` |
| `payload` | `Map<String, String>?` | 타입별 부가 정보 |

열거형(`ConfigChange` · `StopReason` · `PermissionStatus` · `DeviceAvailability` · `LogLevel`)은 마이너 버전에서 값이 늘 수 있습니다 — `when` 에 `else` 를 둡니다.

## 제약

* `suspend` API 는 어느 코루틴에서든 호출 가능. `identify` · `discardPendingPositions` · `pause` · `resume` 은 메인 스레드에서 사용합니다.
* UWB 측위는 포그라운드 전용이며 백그라운드에서 멈추고 돌아오면 다시 시작합니다.
* 좌표 버퍼는 앱상 메모리에 임시 저장되며 강제 종료 시 미전송 좌표는 사라집니다.
* 에뮬레이터에서는 측위할 수 없습니다.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.