igloo
Docs / igloohome / BLE SDK / Getting Started

Getting Started

Install the IglooHome BLE SDK and make your first lock operation.


Requirements

Requirement Version
Android minSdk 24 (Android 7.0)
Android compileSdk 35
Kotlin 2.0.21+
Java compatibility 1.8
iOS deployment target 15.0+
Xcode 16+
Swift 6.0+ (Swift 6 language mode)

BLE requires a physical iOS device — the iOS Simulator does not support Bluetooth.


Installation (Android)

1. Add the GitLab Maven Repository

In your project-level settings.gradle.kts:

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven {
            url = uri("https://gitlab.com/api/v4/projects/64441730/packages/maven")
            credentials(HttpHeaderCredentials::class) {
                name = "Private-Token"
                value = providers.gradleProperty("iglooGitlabToken").get()
            }
            authentication {
                create<HttpHeaderAuthentication>("header")
            }
        }
    }
}

Add your GitLab Personal Access Token to gradle.properties:

iglooGitlabToken=glpat-XXXXXXXXXXXXXXXXXXXX

Security: Do not commit gradle.properties with tokens to version control. Add it to .gitignore.

2. Add the SDK Dependency

In your module-level build.gradle.kts:

dependencies {
    implementation("co.igloo.home:sdk:3.5.0")
}

Installation (iOS)

1. Add the Package

Via Swift Package Manager, in Xcode: File → Add Package Dependencies…, or in Package.swift:

dependencies: [
    .package(url: "https://gitlab.com/igloohome/iglooaccess-ios-sdk.git", from: "2.0.0")
]

Add the IgloohomeSDK product to your target's dependencies.

Note: the package repo is private — Xcode must be configured with credentials (SSH key or a GitLab personal access token) that can read gitlab.com/igloohome/iglooaccess-ios-sdk.

Alternatively, via CocoaPods:

pod 'IgloohomeSDK', :git => 'https://gitlab.com/igloohome/iglooaccess-ios-sdk.git', :tag => '2.0.0'

Set Build Libraries for Distribution (BUILD_LIBRARY_FOR_DISTRIBUTION = YES) on your app target — the SDK links a prebuilt IglooSDKCore.xcframework.

2. Import

import IgloohomeSDK
import IglooSDKCore

IglooSDKCore provides the shared enums/structs used across the API (ScanResult, LockingDirection, CalibrationStep, etc.) and must be imported alongside IgloohomeSDK even though the entry point (IglooPlugin) lives in IgloohomeSDK.


Permissions

AndroidManifest.xml

<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Info.plist (iOS)

<key>NSBluetoothAlwaysUsageDescription</key>
<string>This application uses Bluetooth to connect to the Lock</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This application uses Bluetooth peripherals</string>

Runtime Permissions

Request BLE permissions before calling any SDK method:

private val blePermissions = arrayOf(
    Manifest.permission.BLUETOOTH_SCAN,
    Manifest.permission.BLUETOOTH_CONNECT,
    Manifest.permission.ACCESS_FINE_LOCATION,
)

private val permissionLauncher = registerForActivityResult(
    ActivityResultContracts.RequestMultiplePermissions()
) { grants ->
    if (grants.values.all { it }) {
        // All permissions granted — safe to use SDK
    }
}

// Call before first SDK use
permissionLauncher.launch(blePermissions)

There is no iOS equivalent of this step — just declare the Info.plist keys above and call SDK methods directly; the OS handles prompting.


Initialization

OAuth Authentication

val sdk = IglooPlugin(context)
// Pass accessToken to each method that requires it
let sdk = IglooPlugin()
// Pass accessToken to each method that requires it

Important: Only one IglooPlugin instance should exist at a time. Multiple instances cause undefined BLE behavior — each holds its own connection state.


Quick Start

// 1. Initialize
val sdk = IglooPlugin(context)

// 2. Scan for nearby locks
try {
    sdk.scanDevice().collect { result ->
        println("Found: ${result.deviceId}, paired=${result.isPaired}, rssi=${result.rssi}")
    }
} catch (e: IglooHomeException.BluetoothException) {
    println("Please enable Bluetooth")
} catch (e: IglooHomeException) {
    println("Scan failed: ${e.message}")
}

// 3. Lock a device
try {
    sdk.lock(deviceId = "IGM4-XXXX", key = guestKey)
    println("Locked")
} catch (e: IglooHomeException.TimeoutException) {
    println("Lock not in range")
} catch (e: IglooHomeException) {
    println("Error: ${e.message}")
}

// 4. Sync device state
try {
    val sync = sdk.sync(
        deviceId = "IGM4-XXXX",
        key = guestKey,
        getDeviceToken = accessToken,
        storeLogsToken = accessToken,
        updateDeviceToken = accessToken,
    )
    println("Battery: ${sync.batteryLevel}%")
} catch (e: IglooHomeException.ConnectionException) {
    println("unexpected bluetooth connection issue")
} catch (e: IglooHomeException.TimeoutException) {
    println("Timed out, try again")
} catch (e: IglooHomeException) {
    println("Sync failed: ${e.message}")
}

// 5. Disconnect when done
sdk.disconnect("IGM4-XXXX")
// 1. Initialize
let sdk = IglooPlugin()

// 2. Scan for nearby locks
let scanTask = Task {
    do {
        for try await result in sdk.scansLock() {
            print("Found: \(result.bluetoothDeviceName), paired=\(result.isPaired)")
        }
    } catch IgloohomeError.bluetoothIsTurnedOff {
        print("Please enable Bluetooth")
    } catch {
        print("Scan failed: \(error.localizedDescription)")
    }
}
// Stop scanning once you've found what you need:
sdk.stopScan()
scanTask.cancel()

// 3. Lock a device
do {
    try await sdk.lock("IGM4-XXXX", key: guestKey)
    print("Locked")
} catch IgloohomeError.timeout {
    print("Lock not in range")
} catch {
    print("Error: \(error.localizedDescription)")
}

// 4. Sync device state — prefer syncWithStatus (sync() is deprecated)
for await status in sdk.syncWithStatus(
    "IGM4-XXXX",
    key: guestKey,
    getDeviceToken: accessToken,
    storeLogsToken: accessToken,
    updateDeviceToken: accessToken
) {
    if status.operation == .GET_BATTERY_LEVEL, status.isSuccess {
        print("Battery synced")
    }
}

// 5. Disconnect when done
try? await sdk.disconnect("IGM4-XXXX")

Next Steps