AVPlayer / AVAudioPlayer - 从 iCloud Drive 播放音频文件 URL(在模拟器上工作但不是 iPhone)+(OSStatus 错误 -54。)
AVPlayer / AVAudioPlayer - Play audio fileURL from iCloud Drive (work on simulator but not iPhone) + (OSStatus error -54.)
我正在制作音频播放器。
使用 .fileImporter
.
从 iCloud Drive 导入文件
我得到的文件 URL 看起来像这样:file:///private/var/mobile/Library/Mobile%20Documents/com~apple~CloudDocs/_Storage/Audio-books/%D0%91%D1%80%D0%B5%D0%BD%D0%B4%D1%8F%D1%82%D0%B8%D0%BD%D0%B0/Audiobook.mp3"
然后我将它传递给音频播放器(试过 AVPlayer 和 AVAudioPlayer)。 都适用于 iOS 模拟器 。
导入后在设备上出现错误:操作无法完成。 (OSStatus 错误 -54。)
我知道这是可能的,名为 Evermusic 的应用程序与设备上的文件完全相同。
- 是否需要授予我播放存储在设备上的音频的权限?
- 如何访问 com~apple~CloudDocs 的 Container?
非常感谢您的帮助,非常感谢任何建议,我真的被困住了。
为了将来参考该项目的回购:https://github.com/yaosamo/AudioPlayer
您需要使用 startAccessingSecurityScopedResource
才能获得对这些文件的读取权限。请参阅文档:
除了@jnpdx的回答还想补充一些细节,还有我的解决方案示例。
几个核心的东西
✅ 对于我的应用程序,如果您需要访问受保护的音频,则需要使用 startAccessingSecurityScopedResource()
❌ 你不能简单地存储 URL 并在以后使用它,事实上你根本不存储文件 URL。您需要在 URL 上使用所谓的 bookmarkData() 并存储它。所以稍后你可以恢复 URL
我是这样导入文件的:
.fileImporter(isPresented: $presentImporter, allowedContentTypes: [.mp3]) { result in
switch result {
case .success(let url):
// Start accessing secured url
let StartAccess = url.startAccessingSecurityScopedResource()
defer {
// Must stop accessing once stop using
if StartAccess {
url.stopAccessingSecurityScopedResource()
}
}
// Creating new book
let newBook = Book(context: viewContext)
let _ = print("---- Access Granted?", url.startAccessingSecurityScopedResource())
// Getting bookmarkData of the URL
let bookmarkData = try? url.bookmarkData()
newBook.name = "\(url.lastPathComponent)"
// Save bookmarkURL into CoreData
newBook.urldata = bookmarkData
// Specifiying parent item in CoreData
newBook.origin = playlist.self
try? viewContext.save()
case .failure(let error):
print(error)
}
}
玩家检索 URL:
func Audioplayer(bookmarkData: Data) {
// Restore security scoped bookmark
var bookmarkDataIsStale = false
let playNow = try? URL(resolvingBookmarkData: bookmarkData, bookmarkDataIsStale: &bookmarkDataIsStale)
do {
player = try AVAudioPlayer(contentsOf: playNow!)
// Delegate listen when audio is finished
player?.delegate = del
NotificationCenter.default.addObserver(forName: NSNotification.Name("ended"), object: nil, queue: .main) { (_) in
player?.stop()
ended = true
let _ = print("---- Book has ended ----")
}
} catch let error {
print("Player Error", error.localizedDescription)
}
player?.prepareToPlay()
player?.play()
}
谢谢你,这里是repo on git.
我正在制作音频播放器。
使用 .fileImporter
.
我得到的文件 URL 看起来像这样:file:///private/var/mobile/Library/Mobile%20Documents/com~apple~CloudDocs/_Storage/Audio-books/%D0%91%D1%80%D0%B5%D0%BD%D0%B4%D1%8F%D1%82%D0%B8%D0%BD%D0%B0/Audiobook.mp3"
然后我将它传递给音频播放器(试过 AVPlayer 和 AVAudioPlayer)。 都适用于 iOS 模拟器 。 导入后在设备上出现错误:操作无法完成。 (OSStatus 错误 -54。)
我知道这是可能的,名为 Evermusic 的应用程序与设备上的文件完全相同。
- 是否需要授予我播放存储在设备上的音频的权限?
- 如何访问 com~apple~CloudDocs 的 Container?
非常感谢您的帮助,非常感谢任何建议,我真的被困住了。 为了将来参考该项目的回购:https://github.com/yaosamo/AudioPlayer
您需要使用 startAccessingSecurityScopedResource
才能获得对这些文件的读取权限。请参阅文档:
除了@jnpdx的回答还想补充一些细节,还有我的解决方案示例。
几个核心的东西
✅ 对于我的应用程序,如果您需要访问受保护的音频,则需要使用 startAccessingSecurityScopedResource()
❌ 你不能简单地存储 URL 并在以后使用它,事实上你根本不存储文件 URL。您需要在 URL 上使用所谓的 bookmarkData() 并存储它。所以稍后你可以恢复 URL
我是这样导入文件的:
.fileImporter(isPresented: $presentImporter, allowedContentTypes: [.mp3]) { result in
switch result {
case .success(let url):
// Start accessing secured url
let StartAccess = url.startAccessingSecurityScopedResource()
defer {
// Must stop accessing once stop using
if StartAccess {
url.stopAccessingSecurityScopedResource()
}
}
// Creating new book
let newBook = Book(context: viewContext)
let _ = print("---- Access Granted?", url.startAccessingSecurityScopedResource())
// Getting bookmarkData of the URL
let bookmarkData = try? url.bookmarkData()
newBook.name = "\(url.lastPathComponent)"
// Save bookmarkURL into CoreData
newBook.urldata = bookmarkData
// Specifiying parent item in CoreData
newBook.origin = playlist.self
try? viewContext.save()
case .failure(let error):
print(error)
}
}
玩家检索 URL:
func Audioplayer(bookmarkData: Data) {
// Restore security scoped bookmark
var bookmarkDataIsStale = false
let playNow = try? URL(resolvingBookmarkData: bookmarkData, bookmarkDataIsStale: &bookmarkDataIsStale)
do {
player = try AVAudioPlayer(contentsOf: playNow!)
// Delegate listen when audio is finished
player?.delegate = del
NotificationCenter.default.addObserver(forName: NSNotification.Name("ended"), object: nil, queue: .main) { (_) in
player?.stop()
ended = true
let _ = print("---- Book has ended ----")
}
} catch let error {
print("Player Error", error.localizedDescription)
}
player?.prepareToPlay()
player?.play()
}
谢谢你,这里是repo on git.