# Background playback for iOS With the background playback feature for iOS, you can adapt the player to play media content while other applications are in the foreground. You need to configure your iOS application to enable this background video playback behavior. You must disconnect the main `AVPlayer` instance from the current context and store it in your **AppDelegate.swift** or **SceneDelegate.swift** file. When you set the `FlowplayerView.avPlayer` property using the `FlowplayerView` class, the player disables certain UI features and other processes that aren't needed in the background. For information related to listening to events, managing media playback, and handling errors, see the following pages: * [Listen for events](/docs/wowza-flowplayer/apple-sdk/listen-for-events/) * [Manage media playback](/docs/wowza-flowplayer/apple-sdk/manage-media-playback/) * [Handle errors](/docs/wowza-flowplayer/apple-sdk/handle-errors/) ## Enable background playback This section describes the general process to enable background playback and provides an example of how to accomplish this task using the **AppDelegate.swift** or **SceneDelegate.swift** file. By default, the player's `enableBackgroundPlayback` property is set to `false` and the player pauses when receding into the background. For more, see the [FlowplayerViewAPI properties](/docs/wowza-flowplayer/apple-sdk/manage-media-playback/#properties-1). ### General process The general process to enable background video playback in your iOS application is outlined in the following steps. For a better understanding, [see our example](/docs/wowza-flowplayer/apple-sdk/ios-features/background-playback/#view-an-example). 1. Add a Background Modes capability for your iOS application. 2. Specify the Background Modes your application requires. Select **Audio, AirPlay, and Picture in Picture**. 3. Connect (foreground playback) or disconnect (background playback) the `AVPlayer` instance in the **AppDelegate.swift** or **SceneDelegate.swift** file. 4. Enable the **`enableBackgroundPlayback`** property of the `FlowplayerViewAPI` protocol. info To learn more about enabling certain capabilities to perform background operations, see Configure background modes. ### View an example In this example, we set up a `UIViewController` subclass, then demonstrate how to manage background playback in the **AppDelegate.swift** or **SceneDelegate.swift** files. Pick the method that best suits your iOS application. Warning Never implement both strategies simultaneously because this will break the player. 1. Start by creating a `MyControllerView` class that's a subclass of `UIViewController`. Within this new class, leverage the `FlowplayerView` class to create a `flowplayerView` instance and enable the `enableBackgroundPlayback` property. We can use this `flowplayerView` instance later in the **AppDelegate.swift** and **SceneDelegate.swift** files. ```swift class MyControllerView: UIViewController { // Declare view and instance of FlowplayerView class public let flowplayerView = FlowplayerView() // Handle view controller's lifecycle override func viewDidLoad() { super.viewDidLoad() view.addSubview(flowplayerView) let someMedia = MediaExternal( url: URL(string: "https://link.to.a.media.file")! ) // Enable background playback flowplayerView.enableBackgroundPlayback = true flowplayerView.load(external: someMedia) } } ``` 2. Use the same `MyControllerView` subclass in the **AppDelegate.swift** file, enabling playback in the background or foreground. You can similarly handle the same `MyControllerView` subclass in the **SceneDelegate.swift** file. Switch between the tabs in the following examples to see each implementation. ```swift AppDelegate.swift // AppDelegate.swift private var storedPlayerInstance: AVPlayer? func applicationDidEnterBackground(_ application: UIApplication) { let topController = window?.rootViewController as? MyControllerView savedPlayerInstance = topController?.flowplayerView.avPlayer // Disconnect main AVPlayer instance and // Continue playback in background topController?.videoController.avPlayer = nil } func applicationWillEnterForeground(_ application: UIApplication) { guard savedPlayerInstance != nil else { return } // Continue playback in foreground let topController = window?.rootViewController as? MyControllerView // Reconnect main AVPlayer instance topController?.flowplayerView.avPlayer = self.savedPlayerInstance self.savedPlayerInstance = nil } ``` ```swift SceneDelegate.swift // SceneDelegate.swift var window: UIWindow? var storedPlayer: AVPlayer? func sceneWillEnterForeground(_: UIScene) { guard let navController = window?.rootViewController as? MyControllerView, let flowplayer = viewController.flowplayer else { return } // Continue playback in foreground flowplayer.avPlayer = storedPlayer storedPlayer = nil } func sceneDidEnterBackground(_: UIScene) { guard let navController = window?.rootViewController as? MyControllerView, let flowplayer = viewController.flowplayer else { return } storedPlayer = flowplayer.avPlayer // Continue playback in background flowplayer.avPlayer = nil } ``` ## Listen to the background state By default, the `enableBackgroundPlayback` property of the player is set to `false`. This means that when the player moves to the background, it pauses. If it returns to the foreground, it doesn't automatically resume playing your media. You can modify this behavior and change the video to play when the app containing the player returns to the foreground. To do so, you can observe the `background` playback state of the player and continue playback. The following examples capture the `background` state and use it to resume video playback when the player returns from the background to the foreground. The first tab relies on the [FlowplayerDelegate](/docs/wowza-flowplayer/apple-sdk/listen-for-events/#flowplayerdelegate) method, while the second tab demonstrates achieving the same goal [using notifications](/docs/wowza-flowplayer/apple-sdk/listen-for-events/#listen-with-the-notificationcenter). ```swift FlowplayerDelegate // Use FlowplayerDelegate to observe playback state change func player(_ player: FlowplayerAPI, didChangePlaybackState state: PlaybackState) { print("PlaybackState changed to: \(state)") // Check if current state is .playing and previous state is .background let wasInBackground = player.playbackStateList.prefix(2) == [ .playing, .background ] // If was in background and transitioning to playing is true, // and the player is paused, continue playback when returning from the background if wasInBackground && player.state == .pause { player.play() } } ``` ```swift NotificationCenter // Declare player variable var player: FlowplayerAPI? // Register notification observer and method to be called when notification is received NotificationCenter.default.addObserver( self, selector: #selector(onReceivedState), name: .flowplayerDidChangePlaybackState, object: nil ) // Set up notification selector // Call onReceivedState method when flowplayerDidChangePlaybackState notification is received @objc private func onReceivedState(_ notification: Notification) { guard let state = notification.object as? PlaybackState else { return } // Check if current state is .playing and previous state is .background let wasInBackground = player.playbackStateList.prefix(2) == [ .playing, .background ] // If was in background and transitioning to playing is true, // and the player is paused, continue playback when returning from the background if wasInBackground && player.state == .pause { player.play() } print("myPlayer did change state to: \(state)") } ```