防止AVPlayer进入后台时暂停?

Prevent AVPlayer from pausing when it enters the background?

我有一个简单的应用程序,其中包含播放 M3U8 内容的 AVPlayer。在应用程序中,我执行以下操作以允许背景音频:

    NSError *audioError;
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&audioError];
    if (audioError == nil)
    {
        [[AVAudioSession sharedInstance] setActive:YES error:nil];
    }

当我按下 phone 上的锁定按钮时,音频暂停。如果我再次按下锁定按钮(查看锁定屏幕),我会看到媒体控件,我可以取消暂停内容以收听音频。

我的问题是,如何防止这种自动暂停,以便在首次按下锁定按钮时继续播放?我尝试了如下操作:

- (id) init
{
    // ...
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleEnteredBackground) name: UIApplicationDidEnterBackgroundNotification object: nil];
    // ...
}

- (void) handleEnteredBackground
{
    // [player play];
    [player performSelector:@selector(play) withObject:nil afterDelay:1];
}

但这似乎不起作用。

经过一番搜索,我发现了我的问题:

https://developer.apple.com/documentation/avfoundation/media_assets_playback_and_editing/creating_a_basic_video_player_ios_and_tvos/playing_audio_from_a_video_asset_in_the_background

If you’re playing audio-only assets, such as MP3 or M4A files, your setup is complete and your app can play background audio. If you need to play the audio portion of a video asset, an additional step is required. If the player’s current item is displaying video on the device, playback of the AVPlayer instance is automatically paused when the app is sent to the background. If you want to continue playing audio, you disconnect the AVPlayer instance from the presentation when entering the background and reconnect it when returning to the foreground.

他们的 (Swift) 示例代码如下所示:

func applicationDidEnterBackground(_ application: UIApplication) {

    // Disconnect the AVPlayer from the presentation when entering background

    // If presenting video with AVPlayerViewController
    playerViewController.player = nil

    // If presenting video with AVPlayerLayer
    playerLayer.player = nil
}

func applicationWillEnterForeground(_ application: UIApplication) {
    // Reconnect the AVPlayer to the presentation when returning to foreground

    // If presenting video with AVPlayerViewController
    playerViewController.player = player

    // If presenting video with AVPlayerLayer
    playerLayer.player = player
}

一个 Objective-C 等价物是:

- (void) applicationDidEnterBackground:(UIApplication*)application
{
    playerViewController.player = nil;
}
- (void) applicationWillEnterForeground:(UIApplication*)application
{
    playerViewController.player = player;
}

或者在我的例子中,播放器被嵌入到视图中并且不受应用程序委托或视图控制器的直接控制,所以我使用了以下内容:

- (id) init
{
    // ...
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleEnteredBackground) name: UIApplicationDidEnterBackgroundNotification object: nil];
    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(handleEnteredForeground) name: UIApplicationDidBecomeActiveNotification object: nil];
    // ...
}

- (void) handleEnteredBackground
{
    controller.player = nil;
}

- (void) handleEnteredForeground
{
    controller.player = player;
}