近期产品大大突然提出一个蛋疼的需求,并表示这是客户要求做的。。。没办法,只能硬着头皮上了。推送使用极光推送集成,集成方式详见极光官方文档。
实现原理
iOS 10以上采用推送扩展(极光必传mutable-content,iOS 10以下不需要)处理,使用iOS原生API AVSpeechSynthesizer实现文字合成语音。


iOS10以下采用固定音频文件播放,比如“你有一笔收款”。
相关代码
iOS 10以下:
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[JPUSHService handleRemoteNotification:userInfo];
completionHandler(UIBackgroundFetchResultNewData);
// iOS 10之前前台没有通知栏
if ([UIDevice currentDevice].systemVersion.floatValue < 10.0 && [UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
// iOS 10以下 极光前台不展示消息栏,此处为自定义内容
[EBBannerView showWithContent:@"交易结果通知"];
// 获取共享域的偏好设置(详见多target数据共享)
NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group.xxx"];
BOOL canSound = [userDefault boolForKey:@"voice"];
if (canSound) {
// 播放refund.wav或collection.wav固定音频文件
if ([refund condition]) {
[self playMusic:@"refund" type:@"wav"];
} else {
[self playMusic:@"collection" type:@"wav"];
}
}
}
}// 播放音频文件
- (void)playMusic:(NSString *)name type:(NSString *)type {
//得到音效文件的地址
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:name ofType:type];
//将地址字符串转换成url
NSURL *soundURL = [NSURL fileURLWithPath:soundFilePath];
//生成系统音效id
AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &_soundFileObject);
//播放系统音效
AudioServicesPlaySystemSound(_soundFileObject);
}iOS 10及以上:
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
self.contentHandler = contentHandler;
self.bestAttemptContent = [request.content mutableCopy];
// iOS 10在有语音播报的情况下 可屏蔽系统提示音,也可根据需求来
self.bestAttemptContent.sound = nil;
// Modify the notification content here...
// 获取共享域的偏好设置
NSUserDefaults *userDefault = [[NSUserDefaults alloc] initWithSuiteName:@"group. xxx"];
// 解析推送自定义参数userInfo
NSDictionary *userInfo = [self dictionaryWithUserInfo:self.bestAttemptContent.userInfo];
BOOL canSound = [userDefault boolForKey:@"voice"];
NSString *voiceString = nil;
if (canSound) {
if ([refund condition]) {
voiceString = [NSString stringWithFormat:@"退款%@元!", userInfo[@"money"]];
} else {
voiceString = [NSString stringWithFormat:@"收款%@元!", userInfo[@"money"]];
}
}
// 语音合成
[self syntheticVoice:voiceString];
self.contentHandler(self.bestAttemptContent);
}- (void)syntheticVoice:(NSString *)string {
// 语音合成
self.synthesizer = [[AVSpeechSynthesizer alloc] init];
AVSpeechUtterance *speechUtterance = [AVSpeechUtterance speechUtteranceWithString:string];
//设置语言类别(不能被识别,返回值为nil)
speechUtterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
//设置语速快慢
speechUtterance.rate = 0.55;
//语音合成器会生成音频
[self.synthesizer speakUtterance:speechUtterance];
}