aircore logo symbol
aircore logo

    Start Here

    What is Aircore?

    Authentication

    Channels

  • SDKs

    SDKs

    • Sync Audio

      iOS

      Quickstart
      Customization
      Samples
      Download SDK
      API Reference

      Android

      (Compose)

      Quickstart
      Sample
      Download SDK
      API Reference

      Android

      (View)

      Quickstart
      Sample
      Download SDK
      API Reference

      Web

      Quickstart
      Samples
      Download SDK
      API Reference

      Flex Audio

      iOS

      Quickstart
      More Options
      Sample
      Download SDK
      API Reference

      Android

      Quickstart
      Download SDK
      API Reference

Flex Audio SDK for iOS: More options

After you add the Flex Audio SDK for iOS to your app using the Quickstart, you can use the options on this page to further customize your integration.

Use a secret API key

Aircore provides two types of API key: publishable and secret. See Authentication for an overview.

The Quickstart uses a publishable API key. This section explains how to use a secret API key instead for better security.

Create a channel

When you get a token using a secret API key, use this syntax for createChannel():

let channel = Engine.sharedInstance.createChannel(sessionAuthToken: TOKEN)

The token determines whether the channel can publish audio.

Update expiring tokens

The sessionAuthTokenNearingExpiry notification tells you when the token used to join a channel is about to expire. You must replace the token to continue using the channel.

Your backend requests a new token from the Aircore provisioning service. Then, your app can update the token for the channel.

This example shows how to handle token expiry notifications:

let channel: Channel

NotificationCenter.default.addObserver(self,
  selector: #selector(onSessionAuthTokenNearingExpiry(_:)),
  name: ChannelNotification.sessionAuthTokenNearingExpiry, object: channel)

@objc func onSessionAuthTokenNearingExpiry(_ notif: NSNotification) {
  // Create a new token in your backend and provide it to the channel
  getNewSessionAuthTokenFromBackend() { newToken in
    channel.updateSessionAuthToken(newToken)
  }
}

You can also change the permissions by updating the token. For example, if a user does not have permission to publish audio when they join a channel, you can provide a new token to give a user permission.

Note: When you update a channel, the new token must have the same user ID and the same channel ID. If one or both does not match, the channel terminates.

Create a muted stream

You can create a muted stream by setting initialAudioMute to true:

import AircoreMedia

// ... Create and join a channel

// Make sure the channel is connected
let channelJoinState = channel.joinState
guard channelJoinState == .joined || channelJoinState == .rejoining else { return }

// Optional parameters
let params = LocalStreamParams()
params.initialAudioMute = true

let localStream = channel.createLocalStream(params: params)
guard let localStream = localStream else { fatalError() } // Handle error case

Add metadata to a local stream

Your app can include metadata with a local stream. For example, you may want to include a user-specified name that other clients can display in the UI.

The metadata is permanent for the local stream, and members of the channel can read it when they receive a RemoteStream object.

The StreamMetadata object contains key-value pairs, where the keys are strings and the values are simple types (string, number, boolean, or null). To attach it to a stream, add it to the metadata parameter of the LocalStreamParams for initialization.

Get notifications for added and removed streams

All remote streams for a channel are listed in its remoteStreams property. Your app can receive notifications when streams are added to or removed:

import AircoreMedia

let channel: Channel

NotificationCenter.default.addObserver(self,
  selector: #selector(onRemoteStreamAdded(_:)),
  name: ChannelNotification.remoteStreamWasAdded, object: channel)

NotificationCenter.default.addObserver(self,
  selector: #selector(onRemoteStreamRemoved(_:)),
  name: ChannelNotification.remoteStreamWasRemoved, object: channel)

For these notifications, the object is the relevant channel and the userInfo dictionary references the added or removed stream.

@objc func onRemoteStreamAdded(_ notif: NSNotification) {
  // You can choose to keep the RemoteStream. Otherwise, you can access it
  // from the channel's remoteStreams property
  let remoteStream = notif.userInfo?[ChannelNotification.Key.remoteStream] as?
  RemoteStream }

Get notifications for stream connection status

You can receive notifications when the connection status for a remote stream changes:

let remoteStream: RemoteStream

NotificationCenter.default.addObserver(self,
  selector: #selector(onRemoteStreamConnectionChange(_:)),
  name: RemoteStreamNotification.connectionStateDidChange,
  object: remoteStream)

@objc func onRemoteStreamConnectionChange(_ notif: NSNotification) {
  // Get the new `connectionState` from the notification
  let connectionStateKey = RemoteStreamNotification.Key.newConnectionState
  guard let state = notif.userInfo?[connectionStateKey] as?
                      RemoteStream.ConnectionState else { return }
  switch state {
    case .connecting:
    case .connected:
    case .terminated:
      // Optionally check the termination cause here
      let terminationCause = remoteStream.terminationCause
  }
}

Configure audio manually

If your app has specific, global audio needs, you can use AudioDeviceConfig to configure how our SDK uses audio.

Deactivating the AVAudioSession when the SDK is idle

If your app has audio that you want to keep playing when joining or leaving a channel, set deactivateAVAudioSessionOnIdle to false.

// The Engine singleton provides access to the `AudioDeviceConfig` object.
let audioDeviceConfig = Engine.sharedInstance.audioDeviceConfig

// Enable the audio device config and disable deactivating the AVAudioSession on idle.
audioDeviceConfig.isEnabled = true
audioDeviceConfig.deactivateAVAudioSessionOnIdle = false

Full manual control of audio

We only recommend changing this setting if you fully understand how iOS audio works with AVAudioSession.

// The Engine singleton provides access to the `AudioDeviceConfig` object.
let audioDeviceConfig = Engine.sharedInstance.audioDeviceConfig

// Disable the audio device config to give your app full control over the AVAudioSession.
// CAUTION: This disables any control the Flex SDK has over the AVAudioSession.
// Make sure to properly configure AVAudioSession for use with the SDK.
audioDeviceConfig.isEnabled = false

If your app controls the AVAudioSession, we recommend that you listen for audio-specific termination causes. These show if your current AVAudioSession setup conflicts with how you are using the SDK.

For example, some values for AVAudioSession.Category do not allow mic access. If you try to start a local stream, it terminates with the cause noMicrophoneAccess.

let channel: Channel

NotificationCenter.default.addObserver(self,
  selector: #selector(onChannelJoinStateChange(_:)),
  name: ChannelNotification.joinStateDidChange, object: channel)

@objc func onChannelJoinStateChange(_ notif: NSNotification) {
  guard let state = notif.userInfo?[ChannelNotification.Key.newJoinState] as?
    Channel.JoinState else { return }
  if state == .terminated && channel.terminationCause == .noAudioOutput {
    // This shows that your app's AVAudioSession settings do not allow you to
    // play audio. Update your settings.
  }
}

let localStream: LocalStream

NotificationCenter.default.addObserver(self,
  selector: #selector(onLocalStreamConnectionChange(_:)),
  name: LocalStreamNotification.connectionStateDidChange, object: localStream)

@objc func onLocalStreamConnectionChange(_ notif: NSNotification) {
  guard let state = notif.userInfo?[LocalStreamNotification.Key.newConnectionState] as?
    LocalStream.ConnectionState else { return }
  if state == .terminated && localStream.terminationCause == .noMicrophoneAccess {
    // This shows that your app's AVAudioSession settings do not allow you to
    // capture audio input. Update your settings.
  }
}

More info

  • See the full API reference.

  • Download our sample app.

  • on this page
  • Flex Audio SDK for iOS: More options

  • Use a secret API key

  • Create a muted stream

  • Add metadata to a local stream

  • Get notifications for added and removed streams

  • Get notifications for stream connection status

  • Configure audio manually

  • More info