公司要求需要做一個類似支付寶的收款的語音播報功能,研究了一天才完成,記錄下來
寫在前面
語音播報功能的實現必須是推送加語音合成,選擇的推送是極光推送,本文最終實現的效果即使APP被殺死也可以進行語音播報
實現
配置推送證書,極光文檔里面有,把極光推送集成進去就不說了
-
語音合成我用的是系統的方法,不過語音死板不好聽,但是使用很簡單,3行代碼就可以,建議使用其他的SDK
AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:@"成功集成語音播報"]; AVSpeechSynthesizer *synth = [[AVSpeechSynthesizer alloc] init]; [synth speakUtterance:utterance];
-
在收到通知的時候使用上面的3行代碼就可以進行語音播報,但是只限于APP前臺運行,當后臺運行的時候語音播報便不可以了,此時需要加入下面代碼讓語音播報可以在后臺運行,但是殺死的情況下不能播報,殺死重新啟動返回后臺也不可以播報. 我是在AppDelegate里面寫入這個方法的
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
把下面的代碼寫入進去
NSError *error = NULL; AVAudioSession *session = [AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayback error:&error]; if(error) { // Do some error handling } [session setActive:YES error:&error]; if (error) { // Do some error handling } // 讓app支持接受遠程控制事件 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
-
讓語音播報在后臺也可以進行的話就需要在
// 在AppDelegate定義屬性 @property (nonatomic, unsafe_unretained) UIBackgroundTaskIdentifier backgroundTaskIdentifier; - (void)applicationWillResignActive:(UIApplication *)application;
里面加入以下的方法
- (void)applicationWillResignActive:(UIApplication *)application { // 開啟后臺處理多媒體事件 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; AVAudioSession *session=[AVAudioSession sharedInstance]; [session setActive:YES error:nil]; // 后臺播放 [session setCategory:AVAudioSessionCategoryPlayback error:nil]; // 這樣做,可以在按home鍵進入后臺后 ,播放一段時間,幾分鐘吧。但是不能持續播放網絡歌曲,若需要持續播放網絡歌曲,還需要申請后臺任務id,具體做法是: _backgroundTaskIdentifier=[AppDelegate backgroundPlayerID:_backgroundTaskIdentifier]; // 其中的_bgTaskId是后臺任務UIBackgroundTaskIdentifier _bgTaskId; } //實現一下backgroundPlayerID:這個方法: +(UIBackgroundTaskIdentifier)backgroundPlayerID:(UIBackgroundTaskIdentifier)backTaskId{ //設置并激活音頻會話類別 AVAudioSession *session=[AVAudioSession sharedInstance]; [session setCategory:AVAudioSessionCategoryPlayback error:nil]; [session setActive:YES error:nil]; //允許應用程序接收遠程控制 [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; //設置后臺任務ID UIBackgroundTaskIdentifier newTaskId=UIBackgroundTaskInvalid; newTaskId=[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil]; if(newTaskId!=UIBackgroundTaskInvalid&&backTaskId!=UIBackgroundTaskInvalid){ [[UIApplication sharedApplication] endBackgroundTask:backTaskId]; } return newTaskId; }
-
到這里就可以進行后臺播報了,但是注意 到這一步只有在程序沒有被殺死的情況下才可以播報, 殺死之后是不能播報的, 所有我們還要進行處理,這時需要使用 UNNotificationServiceExtension.
-
創建 UNNotificationServiceExtension
填寫文件名,邊創建好了
WX20170623-102242@2x.png
-
-
在 NotificationService.m 里面有一個方法
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler;
此時把語音播報寫進去就可以了
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler { self.contentHandler = contentHandler; self.bestAttemptContent = [request.content mutableCopy]; // Modify the notification content here... self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title]; NSString *content = request.content.userInfo[@"aps"][@"alert"][@"body"]; AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:content]; AVSpeechSynthesizer *synth = [[AVSpeechSynthesizer alloc] init]; [synth speakUtterance:utterance]; self.contentHandler(self.bestAttemptContent); }
-
認為到這里就完成了?,NO!在發送推送的時候還需要在極光推送服務里面配置一下
WX20170623-103137.png
到這一步的時候,后臺播報就可以執行了, 但是 此播報服務只能在 iOS10 系統之后才可以進行, 如果想適配iOS9之前的只能做一個固定的音頻文件放到項目里面,比如支付寶的的到賬提醒, 然后在推送的時候
這時候就可以完美播放音頻文件了, 提醒: 如果不需要動態的語音播放, 直接可以使用這個方法,不需要配置 UNNotificationServiceExtension 和后臺播放了,因為這個方法是系統認為推送的提示音