簡體   English   中英

刪除並還原AVPlayer以啟用背景視頻播放

[英]Remove and restore AVPlayer to enable background video playback

我有一個播放視頻的UIWebView 我希望視頻在應用程序進入后台狀態后繼續播放。 在Apple的技術問答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#>;時的操作感到困惑<#Get your player view#>; 有人可以弄清楚這是什么意思和/或如何在Swift中進行嗎?

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

試試這個,我希望它是可行的!

大概您有一個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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM