iOS 退款(或订单)推送消息语音播报

近期无知经理突然提出一个蛋疼的需求,并表示这是“客户和市场强制要求”做的。。。没办法,只能硬着头皮上了。


之前采用的是静默推送+普通推送,而且网上大部分资料也默认使用的是静默推送方式。据我所知,该方案有一定的缺陷:

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实现文字合成语音。





  • iOS10以下采用固定音频文件播放,比如“您有一条新订单,请及时处理!”。


    相关代码

    - (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];
    }
    君凯商联网-iOS-字唐名僧





版权声明:本文为u010960265原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。