Multiple players for iOS
With v4.4.0 of the Wowza Flowplayer Apple SDK, we added multiple player support to integrate more than one player simultaneously in your iOS applications.
This feature is helpful when you intend to play two different media sources within the same user interface. Both player instances containing the media can be controlled separately as they function independently of each other.
info
To view an example of this feature, see the iOS Example application in our apple-sdk-releases repository. The multi-player examples contain a video-on-demand (VOD) sample that incorporates two different players in the same view.
For information related to listening to events, managing media playback, and handling errors, see these pages:
Identify a player instance
To manage each view instance, you can use the id
property of the FlowplayerAPI protocol. By default, the view randomly generates and emits the value of this property. However, you can also set a custom string identifier.
This section provides examples of how to identify a player instance, then use the delegate pattern or the notification dispatch mechanism to perform a certain action.
Use delegation to identify a player
You can use the delegate pattern to listen for and capture the id
of a view that's triggered a specific event.
The following example monitors changes in the player's state and responds based on which player instance triggered the state change. For an event listeners reference, see Listen for events with the delegate method.
Example
// Declare player instances
let mainPlayer = FlowplayerView()
let secondaryPlayer = FlowplayerView()
// Set delegate property and conform to FlowplayerDelegate protocol
mainPlayer.delegate = self
secondaryPlayer.delegate = self
// Use FlowplayerDelegate protocol to observe and respond to player state changes
func player(player: FlowplayerAPI, didChangeState state: PlayerState) {
// Compare id property of mainPlayer variable and player parameter
guard mainPlayer.id == player.id else {
// If not equal, indicate event was triggered by secondaryPlayer instance
print("secondaryPlayer triggered this event")
return
}
// If equal, indicate event was triggered by mainPlayer instance
print("mainPlayer changed the state to: \(state)")
}
Use notifications to identify a player
You can also use the notification dispatch mechanism in the Wowza Flowplayer Apple SDK to detect the id
of the player and respond to player events.
The following code snippet sets up a notification observer for changes in the player's state. When a state notification is received, it checks the player's identifier and performs a certain action based on which player triggered the event. For more information, see Listen for events with the NotificationCenter.
Example
// Declare player instances
let mainPlayer = FlowplayerView()
let secondaryPlayer = FlowplayerView()
// Register observer for flowplayerDidChangeState notification
NotificationCenter.default.addObserver(
self,
selector: #selector(onReceivedState),
name: .flowplayerDidChangeState,
object: nil
)
// Call onReceivedState method when notification is received
@objc
private func onReceivedState(_ notification: Notification) {
guard
// Retrieve id from notification's user info and check if it matches mainPlayer id
let id = notification.userInfo?[\FlowplayerAPI.id] as? String,
mainPlayer.id == id
else {
// If not equal, indicate event was triggered by secondaryPlayer instance
print("myOtherPlayer triggered this event")
return
}
guard let state = notification.object as? PlayerState else {
return
}
// If equal, indicate event was triggered by mainPlayer instance
print("mainPlayer changed state to: \(state)")
}
Set a custom player identifier
The player's default behavior randomly generates and emits the value of an id
property to identify each player instance. You can also set a player id
that uses a custom string. This is helpful when you have a requirement to use a specific identifier for your player instance.
To set up a player with a custom id
, use this FlowplayerView
initializer:
public init(avPlayer: AVPlayer? = nil, id: String? = nil)
When you initialize a FlowplayerView programmatically, add the initializer and replace the [some-id]
placeholder with a desired ID value:
// Create instance of FlowplayerView, initialize it with avPlayer and id parameters
let flowplayerView = FlowplayerView(avPlayer: nil, id: "[some-id]")
The avPlayer
and id
parameters are optional. If avPlayer
is omitted, the FlowplayerView
class creates its own AVPlayer
instance instead of using an instance you provide.
Feature Limitations
This section outlines limitations to consider when using multiple players at the same time in your iOS applications.
Handling full-screen mode
If using the FlowplayerView
class to render multiple player instances at once, some limitations exist when managing full-screen behavior.
Multiple players in the same UIViewController
class can't enter the full-screen display simply with device rotation. This occurs because each FlowplayerView
instance doesn't know what triggered the orientation change, which could have been caused by user action or another player instance.
For this reason, disable the following properties for all FlowplayerView
instances used inside a single UIViewController
class:
// Player isn't forced into full-screen mode when orientation change occurs
flowplayerView.orientationControlsFullscreen = false
// Player isn't forced to rotate into landscape mode when entering full-screen mode
flowplayerView.fullscreenControlsOrientation = false
info
If you would still like to have a single FlowplayerView
instance go into full-screen mode when the device orientation changes, set the fullscreenControlsOrientation
property to true
for that specific instance. Make sure to disable the same property for all other instances of FlowplayerView
.
To learn more, see Enter or exit full-screen mode and the FlowplayerViewAPI properties.