zoukankan      html  css  js  c++  java
  • 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】添加支持后台播放时,可能会被苹果拒审。

  • 相关阅读:
    UVa 1451 Average (斜率优化)
    POJ 1160 Post Office (四边形不等式优化DP)
    HDU 3507 Print Article (斜率DP)
    LightOJ 1427 Substring Frequency (II) (AC自动机)
    UVa 10245 The Closest Pair Problem (分治)
    POJ 1741 Tree (树分治)
    HDU 3487 Play with Chain (Splay)
    POJ 2828 Buy Tickets (线段树)
    HDU 3723 Delta Wave (高精度+calelan数)
    UVa 1625 Color Length (DP)
  • 原文地址:https://www.cnblogs.com/yuhao309/p/9914350.html
Copyright © 2011-2022 走看看