我正在尝试播放来自通知扩展程序的远程音频文件
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
//...
let url = URL(string: "https://firebasestorage.googleapis.com/v0/b/XXX.appspot.com/o/XXXXXXX?alt=media&token=XXXXXXX")
let item = AVPlayerItem(url: url!)
NotificationCenter.default.addObserver(self, selector: #selector(playerDidFinishPlaying), name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: item)
let player = AVPlayer(playerItem: item)
player.play()
}
但没有任何反应。
在应用程序的功能中,我启用了以下后台模式:“音频,AirPlay和PiP”,“后台提取”,“远程通知”
我需要在通知到达时播放声音而无需用户互动。 此外,媒体附件不是一种选择,因为iOS 10支持是强制性的。
UPD:我试过这个
func download(url: URL) {
URLSession.shared.downloadTask(with: url, completionHandler: { _, _, error in
if let error = error {
print(error)
}
self.play(url: url)
}).resume()
}
func play(url: URL) {
let player = try! AVAudioPlayer(contentsOf: url)
player.prepareToPlay()
player.volume = 1.0
player.play()
}
也没有发生任何事情
答案 0 :(得分:1)
现在可以在iOS 13中实现。如果消息被删除,我将在此处复制消息的内容。 https://forums.developer.apple.com/thread/118404Correct
KevinE于2019年7月30日5:11 PM回答
您的应用应如何运作的细节差异很大 取决于您的特定用例和应用设计,但我们的一般 建议您使用即按即说应用程序 标准的推送通知,而不是用于消息传递的PushKit。 更具体地说,在接收方,您的通知服务 扩展程序应下载相关音频并将该音频附加到 您的特定邮件。
为了支持该方法,从iOS 13开始,系统会寻找 应用程序组容器中可能存在的声音文件以及 预先存在的搜索位置。该文档尚未更新 为此(),但是有头文件文档描述了 “ UNNotificationSound.h”中“ soundNamed:”的注释中的详细信息:
//要为通知播放的声音文件。声音一定是 在应用程序数据容器的“库/声音”文件夹中或 应用程序组数据容器的“库/声音”文件夹。如果文件是 在容器中找不到,系统将在应用程序的捆绑包中查找。
详细说明一下,我们在下面查找声音文件 订单和位置:
您的应用程序将容器直接放置在“库/声音”中。您的应用组 目录名为“ Library / Sounds”的目录中。 这里要记住的主要事情:
目录2是“库/声音”,而不仅仅是“声音”。你需要 创建一个“ Library”目录,其中包含“ Sounds”目录,而不是 只是一个“声音”目录。应用程序直接容器仍然是 我们将排名第一,因此您需要注意自己的工作方式 为文件命名。我建议使用组目录 对于所有声音或遵循两种不同的命名约定 位置,使其永不碰撞。您的网络服务扩展 无法查看目录#1的内容,因此无法知道是否或 没有一个特定的名称会发生冲突。
答案 1 :(得分:1)
感谢 TALE 的回答,我已经实现了
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.receivedRequest = request;
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
if (request.content.userInfo != nil && request.content.userInfo[@"audioUrl"] != nil) {
NSURL* audioUrl = [NSURL URLWithString:request.content.userInfo[@"audioUrl"]];
NSString* audioName = audioUrl.lastPathComponent;
[[[NSURLSession sharedSession] downloadTaskWithURL:audioUrl completionHandler: ^void (NSURL* location, NSURLResponse* response, NSError* error) {
if (location == nil) {
contentHandler(self.bestAttemptContent);
NSLog(@"%@", error);
return;
}
NSFileManager* fileMan = [NSFileManager defaultManager];
NSString* containerPath = [fileMan containerURLForSecurityApplicationGroupIdentifier:@"group.com.example"].path; // Put your app group id here
NSString* soundDir = [containerPath stringByAppendingString:@"/Library/Sounds"];
NSError* errorOut;
if (![fileMan fileExistsAtPath:soundDir]) {
[fileMan createDirectoryAtPath:soundDir withIntermediateDirectories:YES attributes:nil error:&errorOut];
} else {
// Delete old files
NSArray<NSString*>* oldFiles = [fileMan contentsOfDirectoryAtPath:soundDir error:&errorOut];
if (oldFiles != nil) {
for (NSString* oldFileName in oldFiles) {
NSString* oldFilePath = [soundDir stringByAppendingString:oldFileName];
[fileMan removeItemAtPath:oldFilePath error:&errorOut];
}
}
}
NSString* soundPath = [soundDir stringByAppendingString:[@"/" stringByAppendingString:audioName]];
NSURL* soundUrl = [NSURL fileURLWithPath:soundPath];
[fileMan copyItemAtURL:location toURL:soundUrl error:&errorOut];
UNNotificationSound* sound = [UNNotificationSound soundNamed:audioName];
self.bestAttemptContent.sound = sound;
contentHandler(self.bestAttemptContent);
}] resume];
return;
}
// Your logic for non-audio notification
self.contentHandler(self.bestAttemptContent);
}
如果您需要 Swift 版本,请随时发表评论
答案 2 :(得分:0)
我认为,根据我之前的经验,我们可以在收到通知时播放Bundle声音文件。意味着,我们必须将声音文件放在应用程序包中,声音文件是app的预定义资源。
如果您想播放不同的声音,请在应用程序包中添加所有声音文件,并使用通知有效负载键添加识别/播放。
For,如果你想播放带有相关通知的ABC文件,那么设置适当的逻辑/ Key with Notification Payload并确定它。
请让我知道你的想法。快乐编码:)
其他参考: Play notification sound using URL
如果您想使用网址播放声音。然后你可以下载这个文件,或者你可以在缓冲特定文件后播放: