• iOS10技术之实现通知服务扩展(NotificationServiceExtension)


    一、简介
    在iOS 10 之前,苹果没有提供通知扩展类的时候,如果想要实现杀进程也可以正常播报语音消息很难,从ios 10添加了这一个通知扩展类后,实现杀进程播报语音就相对简单很多了。
    Notification Service Extension 就是苹果在 iOS 10的新系统中为我们添加的新特性,这个新特性就能帮助我们用来解决杀死进程正常语音播报。流程如下:
    Server-Side App —》Notification Payload —》APNS —》Server Extension —》Modified Payload —》Notification Content

    二、实现详细步骤
    1、创建一个通知扩展类
    Xcode -> File -> New -> Target -> Notification Service Extension

    2、添加语音播报逻辑代码
    【1】使用苹果官方提供的AVFoundation框架里面的AVSpeechSynthesizer,AVSpeechSynthesisVoice,AVSpeechUtterance。打开NotificationSE文件夹,在NotificationService.m 文件中,添加语音播报逻辑代码。
    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
        
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
        
        //修改通知内容
        self.bestAttemptContent.title = [NSString stringWithFormat:@"%@ [modified]", self.bestAttemptContent.title];
        
        //如果想解决当同时推送了多条消息,这时我们想多条消息一条一条的挨个播报,我们就需要将此行代码注释
        //self.contentHandler(self.bestAttemptContent);
        
        //获取通知信息数据:语音播报的文案 + 通知栏的title + 以及通知内容
        NSDictionary* infoDict=self.bestAttemptContent.userInfo;
        
        //调用语音合成并播放出语音方法
        [self playVoiceWithContent:infoDict[@"content"]];

    }

    - (void)serviceExtensionTimeWillExpire {
        
        self.contentHandler(self.bestAttemptContent);
        
    }

    -(void)playVoiceWithContent:(NSString *)content{
        
        AVSpeechUtterance* utterance=[AVSpeechUtterance speechUtteranceWithString:content];
        utterance.rate = 0.5;
        utterance.voice = self.synthesisVoice;
        [self.synthesizer speakUtterance:utterance];
        
    }

    #pragma mark - <AVSpeechSynthesizerDelegate>
    // 新增语音播放代理函数,在语音播报完成的代理函数中,我们添加下面的一行回调代码
    -(void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance *)utterance
    {
        self.contentHandler(self.bestAttemptContent);
        
    }

    #pragma mark - Lazy Loading
    - (AVSpeechSynthesisVoice *)synthesisVoice {
        if (!_synthesisVoice) {
            _synthesisVoice = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
            
        }
        return _synthesisVoice;
    }

    - (AVSpeechSynthesizer *)synthesizer {
        if (!_synthesizer) {
            _synthesizer = [[AVSpeechSynthesizer alloc] init];
            _synthesizer.delegate = self;//设置委托
        }
        return _synthesizer;
    }

    3、设置支持后台播放
    Xcode -> Targets -> Capabilities -> Background Modes -> 勾选第一项和最后两项

    4、iOS10 以下系统如何实现串行播报
    在AppDelegate.m文件中,添加如下代码:
    //监听通知函数中调用添加数据到队列
    -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
    {
        
        [self addOperation:@"语音内容"];
        
    }

    #pragma mark - 推送通知(主队列管理)
    - (void)addOperation:(NSString *)title {
        
        [[self mainQueue] addOperation:[self customOperation:title]];
        
    }

    - (NSOperationQueue *)mainQueue {
        
        return [NSOperationQueue mainQueue];
        
    }

    - (NSOperation *)customOperation:(NSString *)content {
        
        NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock:^{
            AVSpeechUtterance *utterance = nil;
            @autoreleasepool {
                utterance = [AVSpeechUtterance speechUtteranceWithString:content];
                utterance.rate = 0.5;
                
            }
            utterance.voice = self.voiceConfig;//合成的语音
            [self.synthConfig speakUtterance:utterance];//播放的语音
            
        }];
        
        return operation;
    }

    #pragma mark - Lazy Loading
    - (AVSpeechSynthesisVoice *)voiceConfig {
        if (_voiceConfig == nil) {
            _voiceConfig = [AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"];
        }
        return _voiceConfig;
        
    }

    - (AVSpeechSynthesizer *)synthConfig {
        if (_synthConfig == nil) {
            _synthConfig = [[AVSpeechSynthesizer alloc] init];
        }
        return _synthConfig;
        
    }

    5、注意事项
    【1】当通知栏收起时,扩展类就会被系统终止,扩展内里面的代码也会终止执行,只有当下一个通知栏弹出来,扩展类就恢复功能。苹果规定,当一条通知达到后,如果在30秒内,还没有呼出通知栏,我就系统强制调用self.contentHandler(self.bestAttemptContent) 来呼出通知栏。
    【2】上面的通知扩展类最低支持iOS系统为 10及10 以上,所以所 iOS10以下的系统,是不支持使用通知扩展的.
    【3】添加支持后台播放时,可能会被苹果拒审。

  • 相关阅读:
    闲着写了一个查看股票的程序
    Oracle10g正则表达式
    跨语言平台的RSA加密、解密、签名、验证算法的实现
    Base64转换:AQAB=65537,你知道为什么吗?
    无题
    07年了,新的一年又开始了
    简单生活
    近期关注
    闲话
    各大网站的WEB服务器分析
  • 原文地址:https://www.cnblogs.com/yuhao309/p/9914350.html
Copyright © 2020-2023  润新知