删除并恢复AVPlayer以启用后台视频播放

时间:2015-07-25 00:28:46

标签: ios swift avplayer

我有UIWebView播放视频。当应用程序进入后台状态时,我希望视频继续播放。在Apple的Technical Q&A QA1668中,他们声明:

  

如果AVPlayer的当前项目正在设备上显示视频   显示,AVPlayer的播放在应用程序时自动暂停   被发送到后台。有两种方法可以阻止这种暂停:

     

禁用播放器项目中的视频曲目(仅限基于文件的内容)。   请参阅清单2.从关联的AVPlayer中删除AVPlayerLayer   (将AVPlayerLayer播放器属性设置为nil)。参见清单3.

以下代码如清单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

我正在尝试将其转换为Swift,但我对在<#Get your player view#>;做什么感到困惑。有人能澄清这意味着什么和/或如何在Swift中解决这个问题?

2 个答案:

答案 0 :(得分:0)

在AppDelegate中

var error: NSError?
var success = AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: &error)
if !success {
 NSLog("Failed to set audio session category.  Error: \(error)")
}

在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()
}

尝试这个我希望它有效!!!!!!!

答案 1 :(得分:0)

据推测,您有一个UIViewController,其中包含正在播放视频的UIWebView。您可以注册该视图控制器,以便在应用程序进入后台以及应用程序变为活动状态时接收通知。

当应用程序进入后台时,您可以递归遍历视图层次结构以查找具有AVPlayerLayer的视图。如果找到一个,可以将播放器保存到实例变量并将图层的播放器设置为nil。

当应用再次变为活动状态时,您可以再次递归浏览视图层次结构以查找相应的视图并恢复播放器。

我使用了类似的方法让AVPlayerViewController在后​​台继续播放视频。

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
}