iOS 本地通知不会在锁定屏幕上播放声音

Posted

技术标签:

【中文标题】iOS 本地通知不会在锁定屏幕上播放声音【英文标题】:iOS local notification doesn't play sound on a locked screen 【发布时间】:2018-01-15 15:29:48 【问题描述】:

我的应用应该通过 iBeacon 测距显示位置感知广告。这没有问题:当“看到”某些信标并安排及时发送的本地通知时,应用程序会在后台唤醒。

问题在于,发送到锁定屏幕的本地通知不会点亮屏幕,甚至不会播放任何声音或振动——这对营销团队来说是一场灾难。

通知发送到前台时声音正常播放,但发送到锁定屏幕时播放失败。

这是我为 UNUserNotificationCenter 安排本地通知的代码:

- (void)scheduleLocalNotificationImageWithTitle:(NSString*)title andBody:(NSString*)body andImagePath:(NSString*)imagePath
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
UNNotificationAction *deleteAction = [UNNotificationAction actionWithIdentifier:@"Close"
                                                                          title:@"Close" options:UNNotificationActionOptionDestructive];

UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:@"NOT_CategoryImage"
                                                                          actions:@[deleteAction] intentIdentifiers:@[]
                                                                          options:UNNotificationCategoryOptionNone];
NSSet *categories = [NSSet setWithObject:category];

[center setNotificationCategories:categories];

UNNotificationAttachment *imageAttachment = [UNNotificationAttachment attachmentWithIdentifier:@"SaleNOTIF_Image" URL:[NSURL fileURLWithPath:imagePath] options:nil error:nil];

UNMutableNotificationContent *content = [UNMutableNotificationContent new];
content.title = title;
content.body = body;
content.sound = [UNNotificationSound defaultSound];
content.attachments = @[imageAttachment];

UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.1 repeats:NO];

NSString *identifier = @"NotificationImage";
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];

[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) 
    if (error != nil) 
        NSLog(@"Something went wrong: %@",error);
    
];

以及在 didFinishLaunching 中 UNUserNotificationCenter 的代码:

    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error)
    if( !error )

    
];
[[UIApplication sharedApplication] registerForRemoteNotifications];


UNNotificationCategory* generalCategory = [UNNotificationCategory
                                           categoryWithIdentifier:@"GENERAL"
                                           actions:@[]
                                           intentIdentifiers:@[]
                                           options:UNNotificationCategoryOptionAllowInCarPlay];



// Register the notification categories.
[center setNotificationCategories:[NSSet setWithObjects:generalCategory, nil]];

我也有中心 willPresentNotification 方法,但据我所知,它只对前景有用。

-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler    
CLS_LOG(@"Userinfo %@", notification.request.content.body);

completionHandler(UNNotificationPresentationOptionSound + UNNotificationPresentationOptionAlert);

任何想法我错过了什么?

【问题讨论】:

【参考方案1】:

好的,我终于发现它在 Apple 公开讨论中使用了 this 线程。

这个故事本身很搞笑:我在办公室建立了我的项目,而应用程序却保持沉默。然后我回到家,继续使用我的 MacBook Pro,然后 - 瞧! - 一切正常。我锁定了我的屏幕,通知弹出并按应有的方式响起。前几天,我带着我的 MacBook 跑到我的办公室并构建了相同的代码,但没有任何改变:我的应用程序就像两天前一样保持沉默。我已经挖掘了包括代理和 GPS 在内的所有内容,但一无所获,因为......

结果证明代码没问题,问题本身就在系统的某个地方。因此,解决方案的关键只是防止您(和您的用户)Apple Watch 重复通知您的应用程序(仅来自 Watch 应用程序)。因为如果它重复它会使 iPhone 静音。

这可能是为了防止通知通过声音和振动触发所有内容,并且只让您知道使用最近的设备发生了令人兴奋的事情(现在手表比任何东西都更近,如果它在您的手腕上)。所以这就是我在家时一切正常的原因:我只是没有戴 Watch,所以它不必重复通知,也不会阻止它们。

我只是希望这可以让其他人在 ios 11 上处理通知时花费大量时间。请记住,总是有 WATCH。

【讨论】:

是的,没错。如果您的手机已解锁,您将被视为正在使用它,因此通知会在那里触发以引起您的注意,如果您的手机已锁定,它们会自动推送到您的手表,因为那时那是“活动”设备。我相信从 watchOS 1 开始就是这样了 :) 这听起来很合理,但确实搞砸了所有的测试和一些 UX。如果我想在文档中的某个地方这么说会很棒,这样开发人员在设计 UX 时就会牢记这一点。我在这件事上没有找到任何东西。也许我只是错过了它? 他们这样做:developer.apple.com/library/content/documentation/General/… 看看“通知在哪里发送”部分 太棒了!谢谢!我猜我错过了,因为只搜索了与 iPhone 相关的东西 :) 谢谢!这让我发疯了,我从来没有意识到它只有在我不戴手表时才有效。

以上是关于iOS 本地通知不会在锁定屏幕上播放声音的主要内容,如果未能解决你的问题,请参考以下文章

推送通知声音在 iOS8 上不起作用

在幻灯片上停止 UILocalNotification 声音以查看

如何检测 UILocalnotification 声音是不是正在播放

iOS:App停用后闹钟App如何播放声音?

如何在本地通知上播放不同的声音文件

自定义声音不播放推送通知