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.