Skip to main content

Android Platform Guide

Complete guide for integrating the MOSA SDK into Android applications.

Requirements​

  • Minimum Android API Level: 24 (Android 7.0 Nougat)
  • Kotlin: 1.8.0 or higher
  • Device: Android device with NFC and BLE support
  • Gradle: 7.0 or higher

Installation​

Gradle (Kotlin DSL)​

Add to your build.gradle.kts:

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

Gradle (Groovy)​

Add to your build.gradle:

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

Maven​

Add to your pom.xml:

<dependency>
<groupId>com.mosadock</groupId>
<artifactId>sdk</artifactId>
<version>1.0.0</version>
</dependency>

Configuration​

AndroidManifest.xml​

Add required permissions and features:

<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>

Initialization​

import to.mosa.lib.dock.MOSADockSDK

val sdk = MOSADockSDK.builder()
.setActivity(this)
.setApiKey("your-api-key")
.setUserId("user-123")
.setAutoRequestPermissions(true)
.setAdvancedLogging(false)
.build()

Direct Initialization​

val sdk = MOSADockSDK.create(
activity = this,
apiKey = "your-api-key",
userId = "user-123",
autoRequestPermissions = true,
enableAdvancedLogging = false
)

Singleton Pattern (Legacy)​

val sdk = MOSADockSDK.getInstance(
activity = this,
apiKey = "your-api-key",
userId = "user-123"
)

Permissions​

Required Permissions​

The SDK requires the following permissions:

Android 12+ (API 31+):

  • BLUETOOTH_CONNECT - Connect to BLE devices
  • BLUETOOTH_SCAN - Scan for BLE devices
  • ACCESS_FINE_LOCATION - Required for BLE scanning
  • NFC - NFC tag reading
  • POST_NOTIFICATIONS - Foreground service notifications (Android 13+)

Android 11 and below:

  • BLUETOOTH - Legacy Bluetooth permission
  • BLUETOOTH_ADMIN - Legacy Bluetooth admin permission
  • ACCESS_FINE_LOCATION - Required for BLE scanning
  • ACCESS_COARSE_LOCATION - Required for Android 9 and below
  • NFC - NFC tag reading

Requesting Permissions​

The SDK can automatically request permissions if setAutoRequestPermissions(true) is set. Alternatively, request manually:

lifecycleScope.launch {
val hasPermissions = sdk.checkAndRequestPermissions()
if (!hasPermissions) {
// Handle permission denial
val missingPermissions = sdk.getMissingPermissions()
showPermissionDialog(missingPermissions)
}
}

Check Permission Status​

if (sdk.hasRequiredPermissions()) {
// All permissions granted
} else {
val missing = sdk.getMissingPermissions()
// Handle missing permissions
}

Device Capabilities​

Check BLE Support​

if (!sdk.isBLESupported()) {
// Device doesn't support BLE
showError("Bluetooth LE is not supported on this device")
return
}

Check NFC Support​

if (!sdk.isNFCSupported()) {
// Device doesn't support NFC
showError("NFC is not supported on this device")
return
}

Check BLE Enabled​

if (!sdk.isBLEEnabled()) {
// Prompt user to enable Bluetooth
val intent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
startActivityForResult(intent, REQUEST_ENABLE_BLE)
}

Check NFC Enabled​

if (!sdk.isNFCEnabled()) {
// Prompt user to enable NFC
val intent = Intent(Settings.ACTION_NFC_SETTINGS)
startActivity(intent)
}

Basic Usage​

Request Unlock Key​

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")
}
}

Perform Dock Operation​

lifecycleScope.launch {
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
}

override fun onDockChainInserted() {
// Chain inserted
}

override fun onDockSecured() {
// Dock secured
}

override fun onBleDisConnected() {
// BLE disconnected
}

override fun onRequestKey() {
// Key request initiated (Android only)
}

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

ProGuard/R8 Rules​

If you're using ProGuard or R8, add these rules to your proguard-rules.pro:

# MOSA SDK
-keep class to.mosa.lib.** { *; }
-keepclassmembers class to.mosa.lib.** { *; }
-dontwarn to.mosa.lib.**

# Keep callback interfaces
-keep interface to.mosa.lib.dock.models.MOSADockSDKCallback { *; }

# Keep data classes
-keep class to.mosa.lib.**.models.** { *; }
-keepclassmembers class to.mosa.lib.**.models.** {
<fields>;
<methods>;
}

BLE Foreground Service​

The SDK uses a Foreground Service for stable BLE connections. This is automatically managed and displays a persistent notification during operations. The notification can be customized by providing a notification channel ID in your app's resources.

Threading​

  • SDK methods are suspend functions and should be called from coroutines
  • Callbacks are invoked on the main thread
  • BLE operations run in a background foreground service

Lifecycle Management​

The SDK handles app lifecycle automatically:

  • Foreground: Full functionality available
  • Background: BLE operations continue via foreground service
  • Terminated: Sessions and events are persisted for sync when app restarts

Error Handling​

Errors are reported via the onError callback with structured MosaError objects:

override fun onError(error: MosaError) {
when (error.errorType) {
MosaErrorType.NFC_DISABLED -> {
// Handle NFC disabled
}
MosaErrorType.BLE_DISABLED -> {
// Handle BLE disabled
}
MosaErrorType.DOCK_TIMEOUT -> {
// Handle timeout
}
else -> {
// Handle other errors
}
}
}

Best Practices​

  1. Initialize SDK Early: Initialize in onCreate() of your main Activity
  2. Check Capabilities: Always check device capabilities before operations
  3. Handle Permissions: Request permissions before dock operations
  4. Implement Callbacks: Implement all callback methods for complete UI updates
  5. Error Handling: Always implement onError callback
  6. Lifecycle: Use lifecycleScope for coroutine-based SDK calls

Next Steps​


For iOS integration, see the iOS Platform Guide.