iOS 收款推送訊息語音播報

weixin_33830216發表於2017-12-04

  近期產品大大突然提出一個蛋疼的需求,並表示這是“客戶和市場強制要求”做的。。。沒辦法,只能硬著頭皮上了。
  之前採用的是靜默推送+普通推送,而且網上大部分資料也預設使用的是靜默推送方式。據我所知,該方案有一定的缺陷:1、部分機器收不到語音播報;2、若需要在後臺或鎖屏狀態下播報語音時,上架會遇到"Audio,AirPlay,and Picture in Picture"和"Background fetch"等問題稽核被拒。通過查閱網上的資料,我改用iOS 10新的API推送擴充套件(UNNotificationServiceExtension),三方SDK使用極光,關於整合方式就不多說了,詳見極光官方文件
  這種方案的特點是:節省大量程式碼,上架簡單,伺服器只需要推一條訊息,但iOS 10以上"mutable-content = 1"必傳,否則程式不走這個擴充套件的Target。

實現原理

  • iOS 10以上採用推送擴充套件(極光必傳mutable-content,iOS 10以下不需要)處理,使用iOS原生API AVSpeechSynthesizer實現文字合成語音。

    2377435-cb8213f67dc44847.png
    WX20171205-105718@2x.png

    2377435-bee8977f80332165.jpg
    螢幕快照 2017-12-04 09.53.17.jpg

  • 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];
}

相關文章