Flex Audio SDK for iOS: Quickstart
The Aircore Flex Audio SDK for iOS allows you to quickly add high-quality, real-time voice chat to your iOS app. This lets you avoid dealing with the complexities of building a real-time system on your own.
This guide provides a basic pathway for adding the Flex Audio SDK to an iOS app.
Before starting
Minimum versions
Xcode: 13.2.1
iOS: 13.0
Limitations
For M1 and M2 Macs, you must run Xcode using Rosetta.
As of Xcode 14, bitcode is deprecated. With older versions of Xcode, turn off bitcode in your project's build settings to use this SDK.
Install the SDK
Open the Xcode workspace for your app.
Click File, then click Add Packages.
Copy and paste this URL into the search bar:
https://github.com/aircoreio/aircore-media-ios
Select the Up to Next Major Version dependency rule.
Click Add Package.
If you see the Choose Package Products dialog, click Add Package.
Xcode automatically links the framework to your project.
Set up your app
Enable background audio
We recommend adding the "Audio" and "Voice Over IP" background modes to your application's project settings. For more details, see Enabling Background Audio in Apple's documentation.
Configure the engine
Engine.sharedInstance
is the central location for configuring this SDK.
Set up the engine once per launch, before you use the framework:
To set the user agent, call the
setUserAgent()
method. This allows for better server-side logging and client information tracking.To set the log directory, call the
setLogDirPath()
method. You can send logs to us for troubleshooting.
Authenticate
In this guide, we use a publishable API key for a quick setup. To get your API key:
Create an app in the Developer Console.
Copy your publishable API key and use it to create channels in the next section.
For an overview of API keys, see Authentication. To use a secret API key with this SDK, see More Options.
Create and use a channel
A channel is a connection to a real-time session with other users. See Channels for a general overview.
Joining a channel allows your app to:
Publish a local stream, which is audio shared to other users
Receive remote streams, which are audio shared from other users
Create a channel
Engine.sharedInstance
is a singleton that produces a channel
object.
To start using a channel:
Call the
createChannel()
method and keep the resultingchannel
object:import AircoreMedia let key = "PUBLISHABLE_API_KEY" // Keep this object around! let channel = Engine.sharedInstance.createChannel( publishableAPIKey: key, userID: "user_id", channelID: "channel_id" ) // Check if the channel was successfully created guard let channel = channel else { fatalError() } // Handle error case // Store the channel somewhere safe channelStorage.channel = channel
To connect to the channel and start receiving audio, call its
join()
method:channelStorage.channel.join()
To set the volume for the channel, change the
outputVolume
property. You can set this before or after joining.
Leave a channel
When you no longer need a channel, call its leave()
method. You can use leave()
before local or remote users join.
Leaving destroys all objects for local and remote streams, releasing system resources used by the channel.
The local channel instance also terminates in these cases:
all references to the channel go out of scope
an unrecoverable error occurs
You cannot rejoin a terminated channel. To return to the session with the same users, create a new channel
.
Track the status of a channel
The joinState
property shows a channel's connection status.
To track changes to this property, use the joinStateDidChange
notification:
let channel: Channel
NotificationCenter.default.addObserver(self,
selector: #selector(onChannelJoinStateChange(_:)),
name: ChannelNotification.joinStateDidChange, object: channel)
@objc func onChannelJoinStateChange(_ notif: NSNotification) {
// Get the join state from the notification and respond accordingly
guard let state = notif.userInfo?[ChannelNotification.Key.newJoinState] as?
Channel.JoinState else { return }
switch state {
case .notJoined:
// The initial state. The channel has not yet connected.
// No interaction with other users is possible.
// NOTE: A notification for .notJoined is not sent.
case .joining:
// The channel is connecting for the first time.
case .joined:
// The channel is connected and automatically plays remote streams.
case .rejoining:
// The channel connected and then disconnected.
// It is now reconnecting.
case .terminated:
// The channel has permanently disconnected. You can check the
// termination cause here.
// NOTE: You can't reuse the channel, but you can detect if the channel
// terminated unexpectedly and either create a new channel or show an
// error to the user.
let terminationCause = channel.terminationCause
}
}
You can use the join state to build your user experience and UI:
In the
.notJoined
state, you can let the user join the channel. Or, you can have your app automatically join the channel.In the
.joined
and.rejoining
states, you can let the user publish a local stream. Or, you can have your app automatically publish a local stream.In the
.joining
,.joined
, and.rejoining
states, you can let the user leave the channel.In the
.terminated
state, you can show the user that the channel is disconnected. You can also let the user create a new channel.
Publish a local stream
Users share audio within a channel as streams. To publish audio to other users, you create a local stream.
Use a channel's
createLocalStream()
method to create a local stream.The channel's join state must be
.joined
or.rejoining
.import AircoreMedia // ... Create and join a channel // Make sure the channel is connected let channelJoinState = channel.joinState guard channelJoinState == .joined || channelJoinState == .rejoining else { return } // Default parameters let params = LocalStreamParams() let localStream = channel.createLocalStream(params: params) guard let localStream = localStream else { fatalError() } // Handle error case
Use
start()
to publish audio from the microphone:// Start the local stream localStream.start() // You can choose to keep the local stream or access it from the channel
Use
muteAudio()
to stop capturing and publishing audio:// Mute the audio localStream.muteAudio(true) // Unmute the audio localStream.muteAudio(false)
To create a muted stream, see More Options.
Stop the stream:
// To stop sending local audio, stop the local stream localStream.stop()
Note: For local streams, muting and unmuting are asynchronous operations. If a channel does not have the allowPublishAudio
permission, unmuting fails.
Get notifications for local streams
The LocalStreamNotification
interface has notifications for mute state, voice activity, and connection state for local streams.
Receive remote streams
After you connect to a channel, your app begins receiving and playing audio published by other users. A RemoteStream
object represents each incoming audio stream from another user.
The Flex Audio SDK receives audio and automatically plays it out through the active output device.
Check remote streams in a channel
To see all active remote streams within a channel, check its remoteStreams
property. You can use this property to show active streams to the user.
To get notifications for added and removed streams, see More Options.
Check the connection to a remote stream
To see if a remote stream is connected, check the connectionState
property.
To get notifications for remote stream connection status, see More Options.
Mute a remote stream
To mute a remote stream, use its muteAudio()
method. When you locally mute a stream, the app still receives the audio but does not play it.
You can check local muting using:
The
localAudioMuteStateDidChange
notificationThe
localAudioMuted
property
The publisher can also mute a stream. You can check remote muting with:
The
remoteAudioMuteStateDidChange
notificationThe
remoteAudioMuted
property
Check for voice activity
To check if a remote stream has audible speech, use the voiceActivity
property.
The voiceActivityStateDidChange
notification shows changes to this property.
Check termination cause
To see why a remote stream ended, check the terminationCause
property.
Terminated streams are removed from the channel's remoteStreams
set and destroyed when your app no longer holds a reference to them.
More info
To continue building your app, see More Options.
See the full API reference.
Download our sample app.