注:此次只记录 iOS 如何在 App 处于后台或者杀死进程的状态下接收推送并语音播报推送内容。
前言,这次是接手他人的项目,之前实现了 App 在前台收到推送并语音播报,这次需求是类似支付宝微信收款在 App 后台或者杀死进程收到推送语音播报推送内容,一开始我以为只是在 App 退到后台的代理方法实现远程推送就完事儿了。结果搞了半天没进展,后来才知道前台接收到的推送是自定义消息,当然在后台无法收到了,如果要想在不更改前台已经实现好的功能前提下支持后台语音播报,那就只能通知和自定义一起推送了。
一、出现的部分问题:
①当 App 在前台的时候也会走消息扩展的方法,所以就出现了2次语音播报的情况;
②讯飞语音在消息扩展里面不会实现;
③同一账号在不同设备上登录后,所有设备都会收到推送;
二、解决方案:
问题①解决方案
// 要想在前台的不接收通知就在进入前台的代理方法中反注册通知
/**
以下两个方法都是 App 从后台进入前台会调用的代理
*/
- (void)applicationWillEnterForeground:(UIApplication *)application {
// App 进入前台反注册通知
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
[[UIApplication sharedApplication]setApplicationIconBadgeNumber:0];
[JPUSHService setBadge:0];
// App 进入前台反注册通知
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
}
// 在 App 退到后台或者杀死进程的时候再注册通知
/**
以下两个方法最好都实现
*/
- (void)applicationWillEnterForeground:(UIApplication *)application;
- (void)applicationWillTerminate:(UIApplication *)application {
[JPUSHService registerForRemoteNotificationTypes:(UIUserNotificationTypeBadge |
UIUserNotificationTypeSound |
UIUserNotificationTypeAlert)
categories:nil];
}
问题②解决方案
/**
导入AVFoundation/AVFoundation.h
需要注意的是消息扩展里面会导入一些自定义类是会报错的,还有全局变量、宏定义在扩展里面出现问题都是正常的。
*/
//初始化语音播报
AVSpeechSynthesizer * av = [[AVSpeechSynthesizer alloc]init];
//设置播报的内容
AVSpeechUtterance * utterance = [[AVSpeechUtterance alloc]initWithString:request.content.userInfo[@"aps"][@"alert"]];
//设置语言类别
AVSpeechSynthesisVoice * voiceType = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
utterance.voice = voiceType;
utterance.volume = 1;
//设置播报语速
utterance.rate = 0.5;
[av speakUtterance:utterance];
问题③解决方案
// 因为我们 后台和 App 约定的推送别名是登录的账号,而登录过该账号的设备就会生成一个 registerID,所以就会出现多设备同时收到推送.
虽然我们在退出登录的时候会将推送别名置为 nil,但这是不够的,需要后台将 registerID 保留当前最新的,就可以解决了。