由于公司的需求要求搞一个类似于支付宝那样的后台推送的语音播报,研究了下文字转语音,以及在iOS允许的一定时间范围内的后台播报语音。
1.首先来讲讲iOS 10.0 的推送,这里就不用什么友盟,极光了。直接看文档用原生的推送。
speech 是我自己简单封装的语音播报类,在git 上有demo
@interface AppDelegate ()@property (nonatomic, strong) TTSpeech *speech;
@property (assign, nonatomic)UIBackgroundTaskIdentifier backIden;//后台运行的标识
@end
@implementation AppDelegate
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
UNAuthorizationOptions types10=UNAuthorizationOptionBadge|UNAuthorizationOptionSound;
//用户权限申请
[center requestAuthorizationWithOptions:types10 completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
//点击允许
} else {
//点击不允许
}
}];
基本设置就这些,注册完了.
//iOS 10 新增2个代理方法
//前台推送过来的时候调用的方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
}
//后台推送的时候调用的方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler {
}
//静默推送回调的方法,后台推送 的字段"content-available":"1" 一定要加 ,否则在后台推送信息代码不会走!
{"aps":{"alert":"This is some fancy message.","badge":8,"sound": "defalut","content-available":"1"}}
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
completionHandler(UIBackgroundFetchResultNewData);
[_speech speakWithText:userInfo[@"aps"][@"alert"]];
NSLog(@"userInfo--%@--", userInfo);
}
重点来了,我们需要申请iOS 后台一段时间,(最起码在iOS 后台允许情况下)
- (void)applicationDidEnterBackground:(UIApplication *)application
{
_backIden = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
//后台结束(被悬挂起)时候调用block ,此时也需要和iOS 系统说下,结束此次借用后台时间(有借有还!)
[[UIApplication sharedApplication] endBackgroundTask:_backIden];
}];
}
自己实际测试,如果不借用后台,那么即使后台允许播报语音也会被系统的一些中断通知中断掉。
TTSpeech .h
#import@interface TTSpeech : NSObject
- (void)speakWithText:(NSString *)text;//语音播报
@end
TTSpeech.m
TTSpeech (){
AVAudioSession *_session;
AVSpeechSynthesizer *_synth;
}
//@property (nonatomic, strong) IFlySpeechSynthesizer *iFlySpeechSynthesizer;
@end
@implementation TTSpeech
- (instancetype)init {
self = [super init];
if (self) {
[self config];
[self openBackground:YES];
}
return self;
}
- (instancetype)initWithBackgroundModes:(BOOL)background {
self = [super init];
if (self) {
[self config];
[self openBackground:background];
}
return self;
}
- (void)config {
_session = [AVAudioSession sharedInstance];
_synth = [[AVSpeechSynthesizer alloc] init];
_synth.delegate = self;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handlerleInterruption:) name:AVAudioSessionInterruptionNotification object:_session];
- (void)handlerleInterruption:(NSNotification *)note {
NSLog(@"%d", [_synth continueSpeaking]);
}
#pragma mark - 是否申请后台语音播报
- (void)openBackground:(BOOL)background {
NSError *error = NULL;
[_session setCategory:AVAudioSessionCategoryPlayback error:&error];
if(error) {
// Do some error handling
NSLog(@"后台播报错误");
}
[_session setActive:YES error:&error];
if (error) {
// Do some error handling
NSLog(@"后台播报错误");
}
}
- (void)speakWithText:(NSString *)text {
AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc] initWithString:text];
utterance.rate = 0.5;
utterance.volume = 0.6;
AVSpeechSynthesisVoice *voice = [AVSpeechSynthesisVoice voiceWithIdentifier:@"com.apple.ttsbundle.siri_female_zh-CN_premium"];//优化音质
utterance.voice = voice;
[_synth speakUtterance:utterance];
}
#pragma mark - 语音播报代理
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didStartSpeechUtterance:(AVSpeechUtterance *)utterance {
NSLog(@"%s",__func__);
}
- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer willSpeakRangeOfSpeechString:(NSRange)characterRange utterance:(AVSpeechUtterance *)utterance {
NSLog(@"%s",__func__);
}