iOS MPNowPlayingInfoCenter 不显示使用 AVPlayer 和 AVAudioSession

问题描述

我正在构建一个广播流媒体应用。声音有效,包括应用程序在后台和手机锁定时。但是,我无法在锁定屏幕上显示 MediaPlayer 信息。

我正在尝试使用 AVPlayerAVAudioSessionMPNowPlayingInfoCenter 的组合。我查看了有关 Stack Overflow (this one,especially) 的其他问题,但他们的解决方案似乎对我不起作用。

我将尝试列出我的应用的重要方面:

Info.plist

添加required background modes: App plays audio or streams audio/video using AirPlay

AppDelegate.swift

我将以下代码添加didFinishLaunchingWithOptions

do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
            print("Playback OK")
            try AVAudioSession.sharedInstance().setActive(true)
            print("Session is Active")
        } catch {
            print(error)
        }

然后我覆盖了remoteControlReceived

override func remoteControlReceived(with event: UIEvent?) {
        let rc = event!.subtype
                print("does this work? \(rc.rawValue)")
    }

流媒体模型

在结构体中,我使用 AVPlayer 创建了一个无线电模型。流成功发送到 ViewController。

视图控制器

在viewDidLoad中,运行如下代码

override func viewDidLoad() {
        super.viewDidLoad()
        self.becomeFirstResponder()
        UIApplication.shared.beginReceivingRemoteControlEvents()
}

我还按照另一个教程覆盖了 ViewController 中的以下两个函数

override var canBecomeFirstResponder: Bool {
        return true;
    }
    
    override func remoteControlReceived(with event: UIEvent?) {
        let type = event?.subtype
        
        if (type == UIEvent.EventSubtype.remoteControlTogglePlayPause) {
            //if ([self.radioManager.player.])
            
        }
        
    }

最后,我编写了以下函数,我在阅读新教程时一直在添加函数。我在流开始播放后运行此函数

func setNowPlayingInfo() {

        
        UIApplication.shared.beginReceivingRemoteControlEvents()
        MPRemoteCommandCenter.shared()
        MPRemoteCommandCenter.shared().playCommand.addTarget {event in
              return .success
            }
            MPRemoteCommandCenter.shared().pauseCommand.addTarget {event in
              return .success
            }
            MPRemoteCommandCenter.shared().nextTrackCommand.addTarget {event in
              return .success
            }
            MPRemoteCommandCenter.shared().prevIoUsTrackCommand.addTarget {event in
              return .success
            }
        
        var NowPlayingInfo = [String: Any]()
        // prepare title and subtitle
        NowPlayingInfo[MPMediaItemPropertyTitle] = "Test"
    
        MPNowPlayingInfoCenter.default().NowPlayingInfo = [
            MPMediaItemPropertyTitle: self.trackTitle.text,MPMediaItemPropertyArtist: self.nameLabel.text
        
        ]
    }

一件奇怪的事情是,当我添加MPNowPlayingInfoCenter.default().playbackState = .playing 行时,会显示 MediaPlayer。但是,当我在实际手机上对其进行测试时(与模拟器相比),该应用会停止运行,因为该属性仅适用于 MacOS。

当应用正在流式传输时,我尝试打开 Youtube,YouTube 视频开始静音。这让我觉得手机可以识别我的应用程序的 AVAudioSession。此外,当我在运行 print(MPNowPlayingInfoCenter.default().NowPlayingInfo?[MPMediaItemPropertyTitle])调用 setNowPlayingInfo() 时,会打印正确的信息。

非常感谢任何建议。对于这个很长的问题,我深表歉意。

编辑

这个问题可能是因为我的 AVPlayer 没有正确初始化?下面是通过委托与视图控制器通信的 .swift 文件中的初始化代码

struct RadioManager {
    var player: AVPlayer = AVPlayer.init()
    var streamPlaying = false
    var badRadioURL = "http://server.badradio.biz:8000/"
    var delegate: RadioManagerDelegate?
    
    mutating func initializeRadio() {
        let urlString = "\(badRadioURL)stream"
        guard let url = URL.init(string: urlString)
                else {
                    return
            }
        let playerItem = AVPlayerItem.init(url: url)
        player = AVPlayer.init(playerItem: playerItem)
    }
    
    mutating func stream() {
        print("loading")
    
        player.play()
        streamPlaying = true
    
    }

解决方法

你的代码看起来不错,你不需要第一响应者的东西。

在您的 AVAudioSession 配置上放置一个断点并确保它确实被调用或检查其日志输出是否存在。

通过锁定屏幕和聆听来确保您的音频在后台正常工作。

您还需要实际播放音频以影响正在播放的信息屏幕。

related

,

好的,我解决了。我的应用程序很好;问题是模拟器的行为不像实际设备。当我在实际的 iPad 上测试时,锁屏信息显示完美。但是,它仍然没有显示在模拟器上。感谢您抽出宝贵时间。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...