Skip to main content

Getting Started

This guide will help you integrate the MOSA SDK into your mobile application. Follow the steps below to get started.

Prerequisites​

Device Requirements​

  • Android: Device with NFC and BLE support, running Android 7.0 (API Level 24) or higher
  • iOS: iPhone 7 or later with NFC and BLE support, running iOS 13.0 or higher
  • Flutter: Same requirements as the native platform

Development Tools​

  • Android: Android Studio with Android SDK
  • iOS: Xcode 12.0 or later
  • Flutter: Flutter SDK (if using Flutter)

API Keys​

You'll need API keys from the MOSA admin dashboard. See API Key Management for instructions on obtaining them.

Installation​

Add Dependency​

Add the SDK dependency to your build.gradle.kts:

dependencies {
implementation("com.mosadock:sdk:1.0.0") // Replace with actual version
}

Or in build.gradle:

dependencies {
implementation 'com.mosadock:sdk:1.0.0'
}

Configure Permissions​

Add required permissions to your AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<!-- Bluetooth permissions -->
<!-- Android 12+ (API 31+) -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

<!-- Legacy Bluetooth (Android 11 and below) -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />

<!-- Location permissions (required for BLE scanning) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- NFC permissions -->
<uses-permission android:name="android.permission.NFC" />

<!-- Foreground service permissions -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <!-- Android 13+ -->

<!-- Network permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- Hardware features -->
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />

</manifest>

Initialize SDK​

After installation, initialize the SDK in your application. The SDK requires certain fields to be configured during initialization.

Required Fields​

  • apiKey (String, required) - Your API key obtained from the MOSA admin dashboard. Used to authenticate API requests. See API Key Management for instructions on obtaining API keys.
  • userId (String, required) - Unique identifier for the current user. This can be a unique ID from your app (e.g., user account ID, or any identifier that uniquely identifies the user). This is used for all dock operations and session management.

Platform-Specific Initialization​

import to.mosa.lib.dock.MOSADockSDK

// Initialize SDK
val sdk = MOSADockSDK.builder()
.setActivity(this) // Activity context
.setApiKey("your-api-key") // Required: Your API key
.setUserId("user-123") // Required: User identifier
.build()

Required Parameters:

  • setActivity(activity) - Activity context for SDK operations
  • setApiKey(apiKey) - Your API key from MOSA admin dashboard
  • setUserId(userId) - Unique user identifier

Request Unlock Key​

The SDK uses unlock keys to authenticate and authorize dock operations. Keys are requested from the backend and expire after 15 minutes.

How It Works​

  1. Session Creation: A session is automatically created (or reused) when requesting certain key types
  2. Key Request: Request an unlock key from the backend with the appropriate type and parameters
  3. Key Usage: Use the key with unlockSmartLock() to perform dock operations

Available Unlock Key Types​

Key TypeUse CaseRequired ArgumentsLocation Type
bikeLockLock a bike at a parking areaareaIdPARKING
bikeUnlockUnlock a bike from a parking dockNonePARKING
rentBikeUnlockRent/unlock a bike from a sharing areaareaIdSHARING
rentBikeLockReturn/lock a bike at a sharing areaareaIdSHARING
testLockPerform a test unlock. The dock won't go into the in-use state and remains ready for use again after attaching the chain back.areaIdPARKING or SHARING

For complete details about unlock keys, including properties, methods, and validation rules, see the API Reference.

Request Unlock Key Example​

lifecycleScope.launch {
val unlockKey = sdk.requestUnlockKey(
type = MOSADockUnlockKeyType.BikeLock,
areaId = "area-123"
)

if (unlockKey != null) {
// Use key for dock operation
performDockOperation(unlockKey)
} else {
// Handle key request failure
showError("Failed to request unlock key")
}
}

Key Request Flow​

Bike Parking​

Bike parking allows users to lock and unlock their bikes at any available dock in a parking area using an unlock key.

Lock Bike​

Lock a bike at a parking dock:

// Step 1: Request lock key
lifecycleScope.launch {
val unlockKey = sdk.requestUnlockKey(
type = MOSADockUnlockKeyType.BikeLock,
areaId = "area-123"
)

if (unlockKey != null) {
// Step 2: Execute lock operation
sdk.unlockSmartLock(
unlockKey = unlockKey,
gfaLocationType = MOSADockLocationType.PARKING,
callback = object : MOSADockSDKCallback {
override fun onNFCScanCompleted(mosaTag: MosaTag) {
// NFC scan completed
}

override fun onBleConnecting() {
// BLE connecting
}

override fun onBleConnected() {
// BLE connected
}

override fun onKeySent() {
// Key sent to dock
}

override fun onDockUnlocked() {
// Dock unlocked
}

override fun onDockChainInserted() {
// Chain inserted - bike locked
}

override fun onDockSecured() {
// Dock secured - operation complete
}

override fun onError(error: MosaError) {
// Handle error
}

// Implement other callbacks...
}
)
}
}

Callback Sequence: onNFCScanCompleted → onBleConnecting → onBleConnected → onKeySent → onDockUnlocked → onDockChainInserted → onDockSecured

Unlock Bike​

Unlock the previously parked bike from the exact dock that was used before. This operation won't work on any other docks:

// Step 1: Request unlock key
lifecycleScope.launch {
val unlockKey = sdk.requestUnlockKey(
type = MOSADockUnlockKeyType.BikeUnlock,
areaId = "area-123" // areaId from session
)

if (unlockKey != null) {
// Step 2: Execute unlock operation
sdk.unlockSmartLock(
unlockKey = unlockKey,
gfaLocationType = MOSADockLocationType.PARKING,
callback = object : MOSADockSDKCallback {
override fun onNFCScanCompleted(mosaTag: MosaTag) {
// NFC scan completed
}

override fun onBleConnecting() {
// BLE connecting
}

override fun onBleConnected() {
// BLE connected
}

override fun onKeySent() {
// Key sent to dock
}

override fun onDockUnlocked() {
// Dock unlocked
}

override fun onDockChainRemoved() {
// Chain removed - bike ready to take
}

override fun onError(error: MosaError) {
// Handle error
}

// Implement other callbacks...
}
)
}
}

Callback Sequence: onNFCScanCompleted → onBleConnecting → onBleConnected → onKeySent → onDockUnlocked → onDockChainRemoved

Bike Sharing​

Bike sharing allows users to rent bikes from sharing areas and return them later.

Rent Bike​

Rent/unlock a bike from a sharing area:

// Step 1: Request unlock key
lifecycleScope.launch {
val unlockKey = sdk.requestUnlockKey(
type = MOSADockUnlockKeyType.RentBikeUnlock,
areaId = "area-123"
)

if (unlockKey != null) {
// Step 2: Execute unlock operation
sdk.unlockSmartLock(
unlockKey = unlockKey,
gfaLocationType = MOSADockLocationType.SHARING,
callback = object : MOSADockSDKCallback {
override fun onNFCScanCompleted(mosaTag: MosaTag) {
// NFC scan completed
}

override fun onBleConnecting() {
// BLE connecting
}

override fun onBleConnected() {
// BLE connected
}

override fun onKeySent() {
// Key sent to dock
}

override fun onDockUnlocked() {
// Dock unlocked
}

override fun onDockChainRemoved() {
// Chain removed - bike ready to take, start rental timer
}

override fun onError(error: MosaError) {
// Handle error
}

// Implement other callbacks...
}
)
}
}

Callback Sequence: onNFCScanCompleted → onBleConnecting → onBleConnected → onKeySent → onDockUnlocked → onDockChainRemoved

Return Bike​

Return/lock a bike at a sharing area:

// Step 1: Request lock key
lifecycleScope.launch {
val unlockKey = sdk.requestUnlockKey(
type = MOSADockUnlockKeyType.RentBikeLock,
areaId = "area-123" // areaId from session
)

if (unlockKey != null) {
// Step 2: Execute lock operation
sdk.unlockSmartLock(
unlockKey = unlockKey,
gfaLocationType = MOSADockLocationType.SHARING,
callback = object : MOSADockSDKCallback {
override fun onNFCScanCompleted(mosaTag: MosaTag) {
// NFC scan completed
}

override fun onBleConnecting() {
// BLE connecting
}

override fun onBleConnected() {
// BLE connected
}

override fun onKeySent() {
// Key sent to dock
}

override fun onDockUnlocked() {
// Dock unlocked
}

override fun onDockChainInserted() {
// Chain inserted - bike locked, stop rental timer
}

override fun onDockSecured() {
// Dock secured - rental complete
}

override fun onError(error: MosaError) {
// Handle error
}

// Implement other callbacks...
}
)
}
}

Callback Sequence: onNFCScanCompleted → onBleConnecting → onBleConnected → onKeySent → onDockUnlocked → onDockChainInserted → onDockSecured

Next Steps​

  1. Understand SDK Callbacks - Learn how to handle SDK events and update your UI
  2. Platform-Specific Guides - Detailed platform documentation and advanced configuration
  3. API Reference - Complete API documentation

For detailed information about unlock keys, including all properties, methods, and validation rules, see the API Reference.