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