? ? 由于公司的需求要求搞一個類似于支付寶那樣的后臺推送的語音播報竿痰,研究了下文字轉(zhuǎn)語音脆粥,以及在iOS允許的一定時間范圍內(nèi)的后臺播報語音。
? ? 1.首先來講講iOS 10.0 的推送影涉,這里就不用什么友盟变隔,極光了。直接看文檔用原生的推送蟹倾。
speech 是我自己簡單封裝的語音播報類匣缘,在git 上有demo
@interface AppDelegate ()@property (nonatomic, strong) TTSpeech *speech;
@property (assign, nonatomic)UIBackgroundTaskIdentifier backIden;//后臺運行的標(biāo)識
@end
@implementation AppDelegate
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
UNAuthorizationOptions types10=UNAuthorizationOptionBadge|UNAuthorizationOptionSound;
//用戶權(quán)限申請
[center requestAuthorizationWithOptions:types10 completionHandler:^(BOOL granted, NSError * _Nullable error) {
? ? if (granted) {
? ? ? ? //點擊允許
? ? } else {
? ? ? ? //點擊不允許
? ? }
}];
基本設(shè)置就這些,注冊完了.
//iOS 10 新增2個代理方法
//前臺推送過來的時候調(diào)用的方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler {
}
//后臺推送的時候調(diào)用的方法
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler ?{
}
//靜默推送回調(diào)的方法鲜棠,后臺推送 的字段"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:^{
? ? //后臺結(jié)束(被懸掛起)時候調(diào)用block ,此時也需要和iOS 系統(tǒng)說下献联,結(jié)束此次借用后臺時間(有借有還J洹)
? ? [[UIApplication sharedApplication] endBackgroundTask:_backIden];
}];
}?
自己實際測試何址,如果不借用后臺,那么即使后臺允許播報語音也會被系統(tǒng)的一些中斷通知中斷掉进胯。
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"];//優(yōu)化音質(zhì)
? ? 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__);
}