Handling System Permissions

The mobile SDK surfaces missing or required system permissions (Bluetooth, internet connectivity, and so on) as CredentialError.userInteractionRequired(action) entries in each credential’s errors array. After activation, observe these errors and handle the specified actions. Errors update automatically as requirements change.


Platform Setup Requirements

First, configure the required platform capabilities.

  1. Suppress Apple Wallet while unlocking with BLE To prevent the Apple Wallet dialog from appearing when your app uses BLE to unlock a door, do the following:

    • Add the requestAutomaticPassPresentationSuppression() call to your app. This method suppresses Apple Wallet while your mobile app is in the foreground and ensures a smoother unlockWithTap experience.

    • Request the com.apple.developer.passkit.pass-presentation-suppression entitlement from Apple.

    Apple Wallet suppression and Bluetooth scanning only apply while the app is in the foreground. Ensure unlock operations are initiated while the app is active.

  2. Enable Bluetooth capability

    Add the required Bluetooth key to your app’s entitlements file:

    <dict>
      <key>com.apple.security.device.bluetooth</key>
      <true/>
    </dict>

Monitoring Permission Errors

Use Combine to watch the published credentials array and handle permission-related errors:

import SeamSDK
import Combine

func startMonitoringPermissionErrors() {
    permissionCancellable = Seam.shared.$credentials
        .map { credentials in
            credentials.flatMap { credential in
                credential.errors.compactMap { error in
                    guard case .userInteractionRequired(let action) = error else { return nil }
                    return action
                }
            }
        }
        .receive(on: RunLoop.main)
        .sink { actions in
            actions.forEach { handlePermissionAction($0) }
        }
}

The mobile SDK automatically clears resolved permission errors once the required permission is granted, reflecting the updated credential state.

Handling Permission Actions

Implement your handler for each action:

fun handleUserInteractionRequired(interaction: SeamRequiredUserInteraction) {
    when (interaction) {
        is SeamRequiredUserInteraction.CompleteOtpAuthorization -> { /* handle OTP authorization */ }
        is SeamRequiredUserInteraction.EnableBluetooth -> { /* handle Bluetooth error */ }
        is SeamRequiredUserInteraction.EnableInternet -> { /* handle Internet connection error*/ }
        is SeamRequiredUserInteraction.GrantPermissions -> { /* handle permissions error*/ }
    }
}

See also

For a complete SwiftUI-based implementation of credential error handling for iOS, see SeamUnlockCardView in the SeamComponents library, which demonstrates observing credential errors and updating the UI accordingly.

Last updated

Was this helpful?