iOS15适配本地通知功能及语音播报探索

简介: iOS15适配本地通知功能及语音播报探索

引言

一年一度的iOS 系统 API适配来了,9 月 14 日起 App Store Connect 已经开放 iOS 15 和 iPadOS 15 App 的提交,同时苹果宣布自 2022 年 4 月起,所有提交至 App Store 的 iOS 和 iPadOS app 都必须使用 Xcode 13 和 iOS 15 SDK 构建。

Xcode 13 正式版包含 iOS 15,iPadOS 15,tvOS 15,watchOS 8 以及 macOS Big Sur 11.3 SDK。Xcode 13 需在 macOS 11.3 及以上版本运行,支持 iOS 9,tvOS 9,watchOS 2 及以上系统设备调试;

也正式支持了 Vim。

Xcode 13 Release Notes: https://developer.apple.com/documentation/xcode-release-notes/xcode-13-release-notes

image.png

I 消息推送

语音播报在iOS15之前的实现思路:

  1. 将你想要播放的音频拆分,放到主程序的包里
  2. 利用Service Extension,在收到服务端的推送的时候,按照顺序发送本地通知
  3. 本地通知的sound就是对应的音频拆分
  4. 将收到的推送的sound设置为nil,避免打断本地推送的语音播报。
  5. 设置队列处理消息推送,避免短时间内收到多个推送导致的问题。
  6. 设置本地通知不弹出横幅(iOS15失效了无法设置)

title和body都设置为空,或者注册通知的时候不启用UNAuthorizationOptionAlert,还要注意的是拓展里面需要设置一下本地化。但是在iOS15如果body为空,将无法播放声音。

<key>CFBundleDevelopmentRegion</key>
 <string>$(DEVELOPMENT_LANGUAGE)</string>

1.1 本地推送适配

推送新特性: iOS15以上的新增属性 interruptionLevel为枚UNNotificationInterruptionLevel

需求:利用本地推送实现消息的语音播报(在扩展里面发本地通知,最后的接收方是主程序)

扩展在收到通知之后 -> 合成音频 -> 存储到扩展的对应路径 -> 扩展自己给自己发一个本地通知那个通知的sound设置成合成文件

iOS15之前的实现思路:

  1. 将你想要播放的音频拆分,放到主程序的包里
  2. 利用Service Extension,在收到服务端的推送的时候,按照顺序发送本地通知
  3. 本地通知的sound就是对应的音频拆分

问题:iOS12.1之后利用本地推送实现消息的语音播报,在iOS15 没有声音。https://kunnan.blog.csdn.net/article/details/103702284

原因:iOS15本地推送新增了中断级别属性 interruptionLevel,对通知进行了分级 。而且通知的内容不能为空。

方案:使用非Passive的中断级别进行本地通知才会有声音,且本地推送一定要有内容,即body不能为空。content.body = @" 不能为空";

image.png

UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
        content.title = @"";
        content.subtitle = @"";
        content.sound = [UNNotificationSound soundNamed:fileName];
        content.badge = @(1);
        if (@available(iOS 15.0, *)) {
            content.interruptionLevel = UNNotificationInterruptionLevelTimeSensitive;//会使手机亮屏且会播放声音;可能会在免打扰模式(焦点模式)下展示
// @"{\"aps\":{\"interruption-level\":\"time-sensitive\"}}";
// @"{\"aps\":{\"interruption-level\":\"active\"}}";
            content.body = @" ";// 本地推送一定要有内容,即body不能为空。
        }else{
            content.body = @"";
        }
        UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.001 repeats:NO];
        // 添加通知的标识符,可以用于移除,更新等操作
        NSString *identifier = [NSString stringWithFormat:@"localPushId%lld", (long long)[[NSDate date] timeIntervalSince1970]];
        UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];
        [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {
            CGFloat waitTime = [self timeForAudioFileWithFileName:fileName];
//            CGFloat waitTime = 0.3;
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(waitTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self localNotificationPushNextFile];
            });
        }];

中断级别目前分为四种:

typedef NS_ENUM(NSUInteger, UNNotificationInterruptionLevel) {
    // Added to the notification list; does not light up screen or play sound
    UNNotificationInterruptionLevelPassive,
    // Presented immediately; Lights up screen and may play a sound
    UNNotificationInterruptionLevelActive,
    // Presented immediately; Lights up screen and may play a sound; May be presented during Do Not Disturb
    UNNotificationInterruptionLevelTimeSensitive,
    // Presented immediately; Lights up screen and plays sound; Always presented during Do Not Disturb; Bypasses mute switch; Includes default critical alert sound if no sound provided
    UNNotificationInterruptionLevelCritical,
} API_AVAILABLE(macos(12.0), ios(15.0), watchos(8.0), tvos(15.0));
  1. Passive:被动类型的通知不会使手机亮屏并且不会播放声音。
  2. Active: 活动类型的通知会使手机亮屏且会播放声音,为默认类型。
  3. Time Sensitive(时间敏感):会使手机亮屏且会播放声音;可能会在免打扰模式(焦点模式)下展示。

设置推送通知数据: 时间敏感的中断级别可以使用“interruption-level” payload key:{"aps":{"interruption-level":"time-sensitive"}}

时效性通知开发者无法直接使用,需要配置对应的权限: a. xcode 开启对应能力

image.png

b. 开发者后台配置appID支持该权限(通过Xcode开启对应能力通常会自动添加)

image.png

  1. Critical(关键):会立刻展示,亮屏,播放声音,无效免打扰模式,并且能够绕过静音,如果没有设置声音则会使用一种默认的声音。

适用于地震等紧急情况,需要特殊申请。

判断是否有时间敏感权限  @property(readonly, nonatomic) UNNotificationSetting timeSensitiveSetting;,如果没有需要提示用户开启。

UNNotificationSetting

typedef NS_ENUM(NSInteger, UNNotificationSetting) {
    // The application does not support this notification type
    UNNotificationSettingNotSupported  = 0,
    // The notification setting is turned off.
    UNNotificationSettingDisabled,
    // The notification setting is turned on.
    UNNotificationSettingEnabled,
} API_AVAILABLE(macos(10.14), ios(10.0), watchos(3.0), tvos(10.0));

1.2 测试

开发者想打ad hot 的话,需要能访问云端管理的分发证书。

image.png

可以使用极光的网页端或者接口进行测试,或者使用smart push。

image.png

1.3 升级JPush iOS SDK

v4.4.0: pod 'JPush' , '4.4.0'

https://docs.jiguang.cn/changelog/jpush/updates_iOS/

更新时间:2021-10-28

Change Log:

SDK适配ios15系统的本地通知功能

富媒体横屏异常兼容性处理

错误信息:ld: library not found for -ljcore-ios-2.3.4

原因:other linker flags 的信息没有自动更新

image.png

解决方案:直接删除other linker flags的jcore信息即可

II 解决新的问题:iOS15 使用本地通知会显示横幅

为了避免iOS15 使用本地通知会显示横幅,采取新的播放方案:Notification Service Extension接到通知之后,去解析出下载播放的音频,下载完毕之后修改sound字段,交由系统播报。

2.1 更换之前的实现思路

iOS15之后的系统通过Notification Service Extension修改推送sounds字段来播报自定义的语音。

+ (instancetype)soundNamed:(UNNotificationSoundName)name;

This method searches for sound files in the following locations, in order: The <app_container>/Library/Sounds directory, where <app_container> is the app’s container directory.

The <group_container>/Library/Sounds directory, where <group_container> is one of the app’s shared group container directories. For information about how to configure group containers for your app, see Configure app groups. The main bundle of the current executable.

sounds除了播放工程主目录(main bundle,打包时候就内置在项目中)和Library/Sounds,还可以播放AppGroup中Library/Sounds的音频 ,于是乎,我们可以在后台合成,然后下载到AppGroup后修改sound字段进行播放。

当音频下载处理完成后调用 self.contentHandler(self.bestAttemptContent);弹出顶部横幅,并开始播报,横幅消失时音频会停止,音频需要控制在在6s之内;下载失败播放默认语音。

如果多条推送同时到达,调用self.contentHandler(self.bestAttemptContent);后,可主动去阻塞线程一定的时长(音频时长)。

2.2 注意事项

  1. 音频支持的格式:aiff、caf、wav、MP3
  2. 如果服务端不配合,不提供合成语音片段的下载地址,就需要在本地合成语音。

2.3 核心代码实现

@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
        self.bestAttemptContent.sound = [UNNotificationSound soundNamed:@"sound.wav"];
    self.contentHandler(self.bestAttemptContent);
}

下载完在本地修改sound字段,交由系统播报

完整代码请看原文:https://kunnan.blog.csdn.net/article/details/121108318

see also

目录
相关文章
|
6月前
|
存储 数据建模 iOS开发
iOS设备功能和框架: 什么是 Core Data,它在 iOS 中的作用是什么?
iOS设备功能和框架: 什么是 Core Data,它在 iOS 中的作用是什么?
100 1
|
6月前
|
定位技术 iOS开发
iOS设备功能和框架: 如何使用 Core Location 获取设备的位置信息?
iOS设备功能和框架: 如何使用 Core Location 获取设备的位置信息?
75 0
|
监控 Android开发 iOS开发
盘点一对一直播源码iOS系统维持平台稳定功能(一):弹性扩缩容
参考代码:弹性扩缩容如何实现?System.out.println("扩容:增加直播平台实例"); currentCapacity++; } private void scaleDown() { System.out.println("缩容:减少直播平台实例");
盘点一对一直播源码iOS系统维持平台稳定功能(一):弹性扩缩容
|
移动开发 安全 前端开发
提升iOS应用安全性:全面代码混淆功能介绍,使用Ipa Guard保护你的应用
iOS加固保护是直接针对ios ipa二进制文件的保护技术,可以对iOS APP中的可执行文件进行深度混淆、加密。使用任何工具都无法逆向、破解还原源文件。对APP进行完整性保护,防止应用程序中的代码及资源文件被恶意篡改。Ipa Guard通过修改 ipa 文件中的 macho 文件中二进制数据(代码模块配置)进行操作,无需源码。不限定开发技术平台。支持oc,swift,cocos2d-x、unity3d、quick-cocos,html5 ,react native等等各种开发技术。Ipa Guard主要包含代码混淆全面、资源文件处理、不需要源代码更安全、调试信息清理、即时测试运行。
|
26天前
|
安全 Android开发 iOS开发
Android vs iOS:探索移动操作系统的设计与功能差异###
【10月更文挑战第20天】 本文深入分析了Android和iOS两个主流移动操作系统在设计哲学、用户体验、技术架构等方面的显著差异。通过对比,揭示了这两种系统各自的独特优势与局限性,并探讨了它们如何塑造了我们的数字生活方式。无论你是开发者还是普通用户,理解这些差异都有助于更好地选择和使用你的移动设备。 ###
49 3
|
4月前
|
人工智能 搜索推荐 iOS开发
苹果发布iOS 18 Beta 4,新增CarPlay 壁纸等多项功能改进
本文首发于公众号“AntDream”,探索iOS 18 Beta 4新功能与改进: CarPlay壁纸、iCloud设置访问优化、相机控制记忆、隐藏文件夹设计变更、深色/浅色模式图标同步、股票应用图标调整、iPhone镜像功能增强、控制中心蓝牙切换键、AssistiveTouch新增Type to Siri等,以及Apple Intelligence暗示。开发者可通过苹果计划提前体验。
103 12
|
4月前
|
IDE API Android开发
安卓与iOS开发环境的差异及适配策略
在移动应用开发的广阔舞台上,Android和iOS两大操作系统各据一方,各自拥有独特的开发环境和工具集。本文旨在深入探讨这两个平台在开发环境上的关键差异,并提供有效的适配策略,帮助开发者优化跨平台开发流程。通过比较Android的Java/Kotlin和iOS的Swift/Objective-C语言特性、IDE的选择、以及API和系统服务的访问方式,本文揭示了两个操作系统在开发实践中的主要分歧点,并提出了一套实用的适配方法,以期为移动开发者提供指导和启示。
|
6月前
|
Android开发 数据安全/隐私保护 iOS开发
ios和安卓测试包发布网站http://fir.im的注册与常用功能
ios和安卓测试包发布网站http://fir.im的注册与常用功能
281 0
ios和安卓测试包发布网站http://fir.im的注册与常用功能
|
6月前
|
iOS开发
SwiftUI适配iOS16导航控制器引起的闪退
SwiftUI适配iOS16导航控制器引起的闪退
74 0
|
6月前
|
监控 iOS开发
iOS15适配问题:viewForSupplementaryElementOfKind表头和表尾复用闪退,UITableView section header多22像素等问题
iOS15适配问题:viewForSupplementaryElementOfKind表头和表尾复用闪退,UITableView section header多22像素等问题
99 0