Reputation: 2816
I have a UIWebView
that plays video. I'd like the video to continue playing when the app goes to the background state. In Apple's Technical Q&A QA1668, they state:
If the AVPlayer's current item is displaying video on the device's display, playback of the AVPlayer is automatically paused when the app is sent to the background. There are two ways to prevent this pause:
Disable the video tracks in the player item (file-based content only). See Listing 2. Remove the AVPlayerLayer from its associated AVPlayer (set the AVPlayerLayer player property to nil). See Listing 3.
The following code is what's shown under Listing 3.
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface MyPlayerLayerView : UIView
@end
@implementation MyPlayerLayerView
- (AVPlayerLayer *)playerLayer {
return (AVPlayerLayer *)[self layer];
}
+ (Class)layerClass {
return [AVPlayerLayer class];
}
@end
@interface MyAppDelegate : UIResponder <UIApplicationDelegate>
...
@end
@implementation MyAppDelegate
...
/* Remove the AVPlayerLayer from its associated AVPlayer
once the app is in the background. */
- (void)applicationDidEnterBackground:(UIApplication *)application {
MyPlayerLayerView *playerView = <#Get your player view#>;
[[playerView playerLayer] setPlayer:nil]; // remove the player
}
/* Restore the AVPlayer when the app is active again. */
- (void)applicationDidBecomeActive:(UIApplication *)application {
MyPlayerLayerView *playerView = <#Get your player view#>;
[[playerView playerLayer] setPlayer:_player]; // restore the player
}
...
@end
I'm trying to convert it to Swift but am confused as to what to do at <#Get your player view#>;
Can someone clarify what that means and/or how to go about this in Swift?
Upvotes: 0
Views: 3115
Reputation: 7103
Presumably, you have a UIViewController
that contains the UIWebView
that is playing the video. You can register that view controller to receive notifications when the app enters the background and when the app becomes active.
When the app enters the background, you can recursively walk through the view hierarchy to find a view with an AVPlayerLayer
. If you find one, you can save the player to an instance variable and set the layer's player to nil.
When the app becomes active again, you can recursively walk through the view hierarchy again to find the appropriate view and restore the player.
I used a similar method to enable an AVPlayerViewController
to continue video playback in the background.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "applicationDidEnterBackgroundNotification:", name: UIApplicationDidEnterBackgroundNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "applicationDidBecomeActiveNotification:", name: UIApplicationDidBecomeActiveNotification, object: nil)
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationDidEnterBackgroundNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationDidBecomeActiveNotification, object: nil)
}
var playerViewToRestore: UIView? = nil
var playerToRestore: AVPlayer? = nil
func applicationDidEnterBackgroundNotification(notification: NSNotification) {
guard let view = findPlayerView() else {
return
}
guard let playerLayer = view.layer as? AVPlayerLayer else {
return
}
playerViewToRestore = view
playerToRestore = playerLayer.player
playerLayer.player = nil
}
func applicationDidBecomeActiveNotification(notification: NSNotification) {
if playerToRestore == nil {
return
}
guard let playerLayer = playerViewToRestore?.layer as? AVPlayerLayer else {
return
}
playerLayer.player = playerToRestore
playerViewToRestore = nil
playerToRestore = nil
}
private func findPlayerView() -> UIView? {
return findViewWithAVPlayerLayer(self.view)
}
private func findViewWithAVPlayerLayer(view: UIView) -> UIView? {
if view.layer.isKindOfClass(AVPlayerLayer) {
return view
}
for v in view.subviews {
if let found = findViewWithAVPlayerLayer(v) {
return found
}
}
return nil
}
Upvotes: 0
Reputation: 972
In AppDelegate
var error: NSError?
var success = AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: &error)
if !success {
NSLog("Failed to set audio session category. Error: \(error)")
}
In MoviePlayerViewController
override func viewDidLoad()
{
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "playBgVideo", name: UIApplicationDidEnterBackgroundNotification, object: nil)
}
func playBgVideo()
{
NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: "hello", userInfo: nil, repeats: false)
}
func hello()
{
movieplayer?.play()
}
try this i hope it's works!!!!!!!
Upvotes: 0