iOS10技術之實現通知服務擴展(NotificationServiceExtension)

1、簡介
在iOS 10 以前,蘋果沒有提供通知擴展類的時候,若是想要實現殺進程也能夠正常播報語音消息很難,從ios 10添加了這一個通知擴展類後,實現殺進程播報語音就相對簡單不少了。
Notification Service Extension 就是蘋果在 iOS 10的新系統中爲咱們添加的新特性,這個新特性就能幫助咱們用來解決殺死進程正常語音播報。流程以下:
Server-Side App —》Notification Payload —》APNS —》Server Extension —》Modified Payload —》Notification Content

2、實現詳細步驟
一、建立一個通知擴展類
Xcode -> File -> New -> Target -> Notification Service Extension

二、添加語音播報邏輯代碼
【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;
}

三、設置支持後臺播放
Xcode -> Targets -> Capabilities -> Background Modes -> 勾選第一項和最後兩項

四、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;
    
}

五、注意事項
【1】當通知欄收起時,擴展類就會被系統終止,擴展內裏面的代碼也會終止執行,只有當下一個通知欄彈出來,擴展類就恢復功能。蘋果規定,當一條通知達到後,若是在30秒內,尚未呼出通知欄,我就係統強制調用self.contentHandler(self.bestAttemptContent) 來呼出通知欄。
【2】上面的通知擴展類最低支持iOS系統爲 10及10 以上,因此所 iOS10如下的系統,是不支持使用通知擴展的.
【3】添加支持後臺播放時,可能會被蘋果拒審。ios

相關文章
相關標籤/搜索