Posts

Post not yet marked as solved
1 Replies
323 Views
In an iOS UNNotificationContentExtension with a media player, I have an AVPlayer which can either play a WAV or an MP4 remotely depending on the push payload userInfo dictionary. I have implemented mediaPlayPauseButtonFrame, mediaPlayPauseButtonTintColor, and mediaPlayPauseButtonType, have overridden canBecomeFirstResponder to force true, and set the view to becomeFirstResponder when the AVPlayer is added. I have implemented the UNNotificationContentExtension protocol's mediaPlay and mediaPause methods. I also have subscribed to the .AVPlayerItemDidPlayToEndTime (NS)Notification and I call a method on the VC when it returns, which calls mediaPause. When the AVPlayer reaches the end, the .AVPlayerItemDidPlayToEndTime Notification is properly emitted, my method is called, and mediaPause is called. However, the media play/pause button provided by UNNotificationContentExtension remains visibly in the "playing" state instead of changing to the "pause" state. The button correctly changes its display state when the user presses the play/pause button manually, so it works. And so, collective Obis Wan Kenobi, what am I doing wrong? I have tried resigning first responder, have no access to the button itself -- as far as I know -- and am wondering where to go next. (This is the only thing not working by the way.) Sanitized example: import UIKit import UserNotifications import UserNotificationsUI class NotificationViewController: UIViewController, UNNotificationContentExtension { // Constants private let viewModel = ... private var mediaPlayer: AVPlayer? private var mediaPlayerLayer: AVPlayerLayer? private var mediaPlayerItem: AVPlayerItem? { mediaPlayer?.currentItem } override var canBecomeFirstResponder: Bool { true } // MARK: - UNNotificationContentExtension var overrides var mediaPlayPauseButtonType: UNNotificationContentExtensionMediaPlayPauseButtonType { return .default } var mediaPlayPauseButtonFrame: CGRect { return CGRect(x: 0.0, y: 0.0, width: 50.0, height: 50.0) } var mediaPlayPauseButtonTintColor: UIColor { return .blue } ... func didReceive(_ notification: UNNotification) { ... // Process userInfo for url } ... @MainActor func playAudio(from: URL) async { let mediaPlayer = AVPlayer(url: url) let mediaPlayerLayer = AVPlayerLayer(player: audioPlayer) ... // view setup mediaPlayerLayer.frame = ... self.mediaPlayer = mediaPlayer self.mediaPlayerLayer = mediaPlayerLayer self.view.layer.addSublayer(mediaPlayerLayer) becomeFirstResponder() } // MARK: - UNNotificationContentExtension func mediaPlay() { mediaPlayer?.play() } func mediaPause() { mediaPlayer?.pause() } // MARK: - Utilities private func subscribe(to item: AVPlayerItem) { NotificationCenter.default.addObserver(self, selector: #selector(playedToEnd), name: .AVPlayerItemDidPlayToEndTime, object: item) } @objc func playedToEnd(notification: NSNotification) { mediaPause() } }
Posted Last updated
.