Почему протоколы MPPlayableContentManager (MPPlayableContentDataSource и MPPlayableContentDelegate) в iOS 13.2 не вызываются?

Аудио-приложение Carplay работало до версии iOS 12.4. Когда я создал приведенный ниже класс, я последовал ответу по этой ссылке, и он отлично работает. Ниже приведен пример кода.

Текущая игра работает на Carplay, но когда приложение открыто на приборной панели, отображается сообщение о невозможности подключения. Я использую Xcode v11.2.1 (11B500), симулятор iOS v13.2.2, iPhone 11 (v13.2.3).

Вы пытались распечатать журналы на initiatePlaybackOfContentItemAt, но он не вызывается. Как вы думаете, что мне не хватает, чтобы она могла работать и быть совместимой с iOS 13 или более поздней версией?

class PlayManager: NSObject {

    static let shared = PlayManager()
    var currentStation: Int64 = 0
    var isRadio: Bool = true
    var contentList: [RadioObj] = []
    let commandCenter = MPRemoteCommandCenter.shared()
    var nowPlayingSongManager: MPNowPlayingInfoCenter?
    var playableContentManager: MPPlayableContentManager?

    override init() {
        super.init()

        let artist = "Play"
        nowPlayingSongManager = MPNowPlayingInfoCenter.default()
        nowPlayingSongManager?.nowPlayingInfo = [
            MPNowPlayingInfoPropertyMediaType : "Audio",
            MPMediaItemPropertyTitle : api.defaults.defaultArtist,
            MPMediaItemPropertyArtist: artist
        ]
        player.initializeMedia(song: api.defaults.defaultArtist, artist: artist, album: api.defaults.appLogo)

        playableContentManager = MPPlayableContentManager.shared()
        playableContentManager?.dataSource = self
        playableContentManager?.delegate = self
    }

    func loadData(){
        api.data.getRadioData(event_source: "carplay") { (done, obj) in

            if done {
                if obj.count > 0 {
                    let indeces: Int = 0
                    api.currentRadio = obj[indeces]
                    api.isRadio = true
                    api.isPodcast = false
                }

                self.contentList = obj
                self.playableContentManager.reloadData()
            }
        }
    }
}


extension PlayManager: MPPlayableContentDelegate, MPPlayableContentDataSource {

    func playableContentManager(_ contentManager: MPPlayableContentManager, initiatePlaybackOfContentItemAt indexPath: IndexPath, completionHandler: @escaping (Error?) -> Void) {

        print("check if its called")

        let indeces: Int = indexPath[0]
        let radio_name = contentList[indeces].name
        let id = contentList[indeces].id
        let radio_logo = contentList[indeces].logo_rounded_url
        let stream_url = contentList[indeces].stream_url
        let hd_stream_url = contentList[indeces].hd_stream_url
        var currentIdentifier = ""

        if contentManager.nowPlayingIdentifiers.count > 0 {
            currentIdentifier = contentManager.nowPlayingIdentifiers[0]
        }

        var newIdenditier = "radio_"

        if let id = id {
            newIdenditier += "\(id)"
        }

        let radioObj = RadioObj()
        radioObj.stream_url = stream_url
        radioObj.hd_stream_url = hd_stream_url
        radioObj.name = radio_name
        radioObj.logo_url = radio_logo

        api.currentRadio = contentList[indeces]
        api.isRadio = true

        if let id = id {
            currentStation = id
        }

        guard let logo = radio_logo, let name = radio_name else { return }

        player.initializeMedia(song: name, artist: api.defaults.defaultArtist, album: api.defaults.appLogo)

        api.download(image: logo) { (image) in
            player.initializeMedia(song: name, artist: api.defaults.defaultArtist, album: image)
        }

        if api.isPlaying && currentIdentifier != newIdenditier {
            contentManager.nowPlayingIdentifiers = [newIdenditier]
            DispatchQueue.main.async {
                player.start()
            }
        }

        onTapSound(contentManager: contentManager, completionHandler: completionHandler, indexPath: indexPath)
    }

    func onTapSound(contentManager:MPPlayableContentManager,completionHandler: @escaping (Error?) -> Void, indexPath : IndexPath){
        completionHandler(nil)
    }

    func numberOfChildItems(at indexPath: IndexPath) -> Int {
        if indexPath.count == 0 {
            return contentList.count
        } else if indexPath.count == 1 {
            let _: Int = indexPath.first ?? 0

        } else if indexPath.count == 2 {

        }
        return 0
    }


    func contentItem(at indexPath: IndexPath) -> MPContentItem? {
        let indeces: Int = indexPath[0]
        let _: Int = indexPath.indices.count

        let radio_name = contentList[indeces].name
        let id = contentList[indeces].id
        let radio_logo = contentList[indeces].car_logo
        if let id = id, let radio_logo = radio_logo {
            let contentItem = MPContentItem(identifier: "radio_\(id)")
            contentItem.title = radio_name
            contentItem.isContainer = false
            contentItem.isPlayable = true
            contentItem.isStreamingContent = true

            DispatchQueue.global().async {
                if let url = URL(string:radio_logo) {
                    do {
                        let radio =  try UIImage(data: Data(contentsOf: url))
                        if let image = radio {

                            let artWork = MPMediaItemArtwork(boundsSize: image.size, requestHandler: { (size) -> UIImage in
                                return image
                            })

                            contentItem.artwork = artWork
                        }
                    } catch{}
                }
            }

            return contentItem
        }

        return MPContentItem()
    }

    open func setupEvents(isRadio isTrue: Bool?) -> PlayManager {
        guard let isTrue = isTrue else { return self }
        commandCenter.playCommand.isEnabled = isTrue


        if isTrue {
            commandCenter.skipForwardCommand.isEnabled = false
            commandCenter.skipBackwardCommand.isEnabled = false
            commandCenter.stopCommand.isEnabled = true
            commandCenter.pauseCommand.isEnabled = false

            if #available(iOS 10.0, *) {
                nowPlayingSongManager?.nowPlayingInfo?[MPNowPlayingInfoPropertyIsLiveStream] = true
            }
        } else {
            commandCenter.stopCommand.isEnabled = false
            commandCenter.pauseCommand.isEnabled = true
        }

        commandCenter.stopCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
            api.isPlaying = false
            player.stop()
            return .success
        }

        commandCenter.pauseCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
            player.pause()
            return .success
        }

        commandCenter.playCommand.addTarget { (event) -> MPRemoteCommandHandlerStatus in
            api.isPlaying = true

            if api.isRadio {
                self.playableContentManager?.nowPlayingIdentifiers = ["radio_\(self.currentStation)"]

                guard let logo = api.currentRadio?.logo_rounded_url, let name = api.currentRadio?.name else { return .noSuchContent }

                api.download(image: logo) { (image) in
                    player.initializeMedia(song: name, artist: api.defaults.defaultArtist, album: image)
                }

                player.start()
            }

            if api.isPodcast {
                player.resume()
            }

            return .success
        }

        return self
    }
}

С более чем 200 строками кода нам много для чтения. Попробуйте удалить как можно больше, чтобы получить что-то, что по-прежнему не работает. Например, быстрая выборочная проверка внизу показывает isPodcast метод, который, вероятно, не связан с проблемой. Продолжайте удалять код до тех пор, пока не получите только наименьший объем кода, в котором все еще есть проблема, и обычно нам намного проще отлаживать.   —  person Don Fuentes    schedule 04.12.2019

См. также:  Создание гистограмм в SwiftUI

У меня другое поведение. При подключении к CarPlay событие запускается, но когда я отключаюсь, ничего не происходит, поэтому я на самом деле просто знаю, когда я подключен к CarPlay, но не когда отключаюсь.   —  person Don Fuentes    schedule 08.06.2021

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 2
  1. Don Fuentes

    Кажется, это ошибка Xcode 11. Я пробовал бета-версию Xcode 13, но результат был тот же.

    В моем случае был пустой белый экран с пустыми вкладками с синим отливом. Затем была показана ошибка: «Невозможно загрузить контент (null)» Скриншот симулятора iOS 13 </ а>.

    Завершил установку симулятора iPhone 5s / iOS 12.4.1.

    На стороне клиента с реальным устройством iOS 13 работала как положено.

  2. Don Fuentes

    Некоторое время назад я отправил в Apple отчет об ошибке. Apple вернулась ко мне и сказала:

    «Нам нужна sysdiagnose и, в идеале, образец кода, воспроизводящий проблему.

    beginLoadingChildItems () — это просто подсказка приложению начать предварительную выборку содержимого в случае, если пользователь коснется строки. Вместо этого более вероятно, что клиентское приложение не предоставляет никакого контента для MPPlayableContentManager «.

    Как видите, этот вопрос ранее задавался на форумах разработчиков Apple.

    Симулятор CarPlay отлично работает с симуляторами Xcode 11 и iOS 12.4, но, похоже, есть проблемы с симуляторами Xcode 11 и iOS 13. Я попытался создать наше приложение на Xcode 11 и запустить его на физическом устройстве iOS 13.1 с физической мультимедийной системой CarPlay в автомобиле, и оно отлично сработало! Это только кажется проблемой симулятора CarPlay.

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: