Аудио-приложение 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
У меня другое поведение. При подключении к CarPlay событие запускается, но когда я отключаюсь, ничего не происходит, поэтому я на самом деле просто знаю, когда я подключен к CarPlay, но не когда отключаюсь. — person Don Fuentes schedule 08.06.2021
Кажется, это ошибка Xcode 11. Я пробовал бета-версию Xcode 13, но результат был тот же.
В моем случае был пустой белый экран с пустыми вкладками с синим отливом. Затем была показана ошибка: «Невозможно загрузить контент (null)» Скриншот симулятора iOS 13 </ а>.
Завершил установку симулятора iPhone 5s / iOS 12.4.1.
На стороне клиента с реальным устройством iOS 13 работала как положено.
Некоторое время назад я отправил в Apple отчет об ошибке. Apple вернулась ко мне и сказала:
Как видите, этот вопрос ранее задавался на форумах разработчиков Apple.
Симулятор CarPlay отлично работает с симуляторами Xcode 11 и iOS 12.4, но, похоже, есть проблемы с симуляторами Xcode 11 и iOS 13. Я попытался создать наше приложение на Xcode 11 и запустить его на физическом устройстве iOS 13.1 с физической мультимедийной системой CarPlay в автомобиле, и оно отлично сработало! Это только кажется проблемой симулятора CarPlay.