Prompt Users to Opt In to Permissions

Opt-in Actions allow you to easily request Push and Location permissions from users, using native permission prompts.

Opt-in Actions Overview

Airship provides support for easily prompting users for certain system-level permissions, via Opt-in Actions. For an overview of all supported actions and where they are available, see the Actions guide.

Supported Opt-in Types

  • Push (built-in) — Grants the app permission to display push notifications
  • Location Opt-in (requires implementation) — Grants the app permission to access the device’s location

Implementing Location Opt-in

Opt-ins are a special type of ActionA configurable behavior that occurs when a user interacts with your message, e.g., opening a web page. that are handled by PermissionsManager. Push Opt-in is supported out-of-the-box, via a built-in delegate. Location Opt-in support is enabled by implementing a custom PermissionDelegate and registering it with PermissionManager to handle the location permission.

Create a Location Permission Delegate

To implement Location Opt-in, create a delegate that handles location permissions:

val delegate = SinglePermissionDelegate(Manifest.permission.ACCESS_COARSE_LOCATION)
import Foundation
import CoreLocation
import AirshipCore
import Combine

class LocationPermissionDelegate: AirshipPermissionDelegate {
    let locationManager = CLLocationManager()

    @MainActor
    func checkPermissionStatus() async -> AirshipCore.AirshipPermissionStatus {
        return self.status
    }

    @MainActor
    func requestPermission() async -> AirshipCore.AirshipPermissionStatus {
        guard (self.status == .notDetermined) else {
            return self.status
        }

        guard (AppStateTracker.shared.state == .active) else {
            return .notDetermined
        }

        locationManager.requestAlwaysAuthorization()
        await waitActive()
        return self.status
    }


    var status: AirshipPermissionStatus {
        switch(locationManager.authorizationStatus) {
        case .notDetermined:
            return .notDetermined
        case .restricted:
            return .denied
        case .denied:
            return .denied
        case .authorizedAlways:
            return .granted
        case .authorizedWhenInUse:
            return .granted
        @unknown default:
            return .notDetermined
        }
    }
}


@MainActor
private func waitActive() async {
    var subscription: AnyCancellable?
    await withCheckedContinuation { continuation in
        subscription = NotificationCenter.default.publisher(for: AppStateTracker.didBecomeActiveNotification)
            .first()
            .sink { _ in
                continuation.resume()
            }
    }

    subscription?.cancel()
}

Register the Permission Delegate

After creating a location PermissionDelegate, you’ll need to register it with PermissionManager so it can be used to handle location opt-ins:

The permission delegate should be set during the onAirshipReady callback.

UAirship.shared().permissionsManager
  .setPermissionDelegate(Permission.LOCATION, delegate)

The permission delegate should be set after takeOff.

Airship.permissionsManager.setDelegate(
  LocationPermissionDelegate(),
  permission: .location
)