app收款语音后台播报方案--ios

2,808 阅读3分钟

ios(高于ios 12 不确定是否可行,做的时候最新的就是12)

基于极光推送服务Notification Service Extension实现在APP后台时,收到极光的推送消息进而播报

前期准备:
ios极光推送基础知识;
Notification Service Extension

首先需要说明的是,后台播报的方案,限制于Notification Service Extension是ios10的新特性,所以只在ios10及其以上版本有效

首先在应用内添加Notification Service Extension:

添加

信息填写

证书编辑

如果引用了音频文件,也需要在应用中导入:

Copy Bundle Resources中选择Add Other...找到对应文件导入即可

代码部分

最后,在创建好了一个Notification Service Extension后,默认内容如下:

在上面的极光推送介绍中,对于ios系统,有个很关键的点:推送时,依赖于ios本身的APNS代理,所以极光推送过来的消息会被Notification Service Extension拦截到
对于Notification Service Extension,有这么一段描述可以帮助我们了解:

Notification Service Extension的作用就是在苹果服务器在给手机推送消息的中间,进入Notification Service Extension, 我们可以在进Notification Service Extension时对推送的消息 进行一次加工,这就是Notification Service Extension的功能的作用。

既然如此

在didReceiveNotificationRequest里:

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
    
    self.contentHandler = contentHandler;
    // 含有推送信息
    self.bestAttemptContent = [request.content mutableCopy];
    // 取出需要的数据
    NSString* alertPath = [self.bestAttemptContent.userInfo objectForKey:@"path"];
    NSString* receiveAmount = [self.bestAttemptContent.userInfo objectForKey:@"receiptAmount"];

需要播报的金额已经取到了,如何播报出声呢?两个方案,AVSpeechSynthesizer或者自定义推送的声音为要播报的音频

ios12.1及以上版本
 
    if ( @available(iOS 12.1, *)) {
        
        //ios 12.1以上版本无法使用AVSpeechSynthesizer,改用收到推送消息后进行本地推送,通过拼接多次自定义推送提示音达到完整的收款语音播报效果
        
        //默认发声文件播放时长,单位为秒
        double defaultAudioPlayTime = 0.5;
        
        //"XX到账"发声文件名
        NSString *receiveAudio = @"g";
        
        //"XX到账"发声文件播放时长
        double receiveAudioTime = 1.5;
        
        //将收款金额转换成发声文件名列表
        // NSString* audioNamesStr = [self translationArabicNum:receiveAmount];
        NSNumber *ireceiveAmount = @([receiveAmount doubleValue]);
        NSMutableArray *audioNamesArr = [self getArrayByNumber:ireceiveAmount];
        NSString *audioNameBefore;
        NSString *audioName;
        
        //根据发声文件名列表轮询推送,每个发声文件分别使用一个字符命名,以便拆分
        for (int i = 0; i < audioNamesArr.count; i+=1) {
            
            //取出当前发声文件名称
            // NSString *audioName = [audioNamesStr substringWithRange:NSMakeRange(i,1)];
            audioName = [audioNamesArr objectAtIndex:i];
            
            //
            if(i != 0){
                audioNameBefore = [audioNamesArr objectAtIndex:(i-1)];
                
                if(audioNameBefore == audioName){
                    audioName =[NSString stringWithFormat:@"%@Copy",audioName];
                }
            }
            
            
            //设置当前文件播放时长
            double playTime = defaultAudioPlayTime;
            if([audioName isEqualToString:receiveAudio]){
                playTime = receiveAudioTime;
            }
            
            dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
            [self registerNotificationWithString:audioName completeHandler:^{
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(playTime* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    dispatch_semaphore_signal(semaphore);
                    
                });
            }];
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        }
        
        self.contentHandler(self.bestAttemptContent);
        
    }

registerNotificationWithString

- (void)registerNotificationWithString:(NSString *)audioName completeHandler:(dispatch_block_t)complete {
    
    [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
        
        if (granted) {
            
            UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc]init];
            
            //将播放提示内容都设置为空,则不会弹窗提示
            content.title = @"";
            content.subtitle = @"";
            content.body = @"";
            // 自定义声音
            content.sound = [UNNotificationSound soundNamed:[NSString stringWithFormat:@"%@.mp3",audioName]];
            content.categoryIdentifier = [NSString stringWithFormat:@"categoryIndentifier%@",audioName];
            
            UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.01 repeats:NO];
            
            UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:[NSString stringWithFormat:@"categoryIndentifier%@",audioName] content:content trigger:trigger];
            
            [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
                
                if (error == nil) {
                    
                    if (complete) {
                        complete();
                    }
                }
            }];
        }
    }];
}
ios12.1以下版本
        //ios 12.1之前版本直接使用AVSpeechSynthesizer播报即可
        self.speechSynthesizer = [[AVSpeechSynthesizer alloc] init];
        
        /*语音播报的内容*/
        NSString* audioPlayContent = receiveAmount;
        audioPlayContent = [@"XX到账" stringByAppendingString:audioPlayContent];
        audioPlayContent = [audioPlayContent stringByAppendingString:@"元"];
        AVSpeechUtterance* speechUtterance = [[AVSpeechUtterance alloc] initWithString:audioPlayContent];
        
        /*设置音量*/
        speechUtterance.volume = 1.0;
        /*设置语调*/
        //speechUtterance.pitchMultiplier = 2.0;
        /*设置哪国语言*/
        speechUtterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
        [self.speechSynthesizer speakUtterance:speechUtterance];
        
        self.contentHandler(self.bestAttemptContent);