Swift. Notification Service Extension實現(xiàn)語音播報

總的來說啸蜜,實現(xiàn)收款到賬語音合成播報,真的是走了很長的路辈挂,踩過很多的坑衬横。避免更多的人重復踩坑,我便記錄走過哪些路终蒂,掉過哪些坑...

一. 先來說第一種蜂林,不推薦再用。因為蘋果粑粑不會給你審核通過的拇泣。

1.推送就不說了噪叙,我們使用的是極光推送
2.語音合成使用的是 AVSpeechSynthesizer
  • 為了app退到后臺進程不被殺掉挫酿,target -> capabilities中開啟了background modes中的audio選項构眯。
    WechatIMG2.jpeg
  • 在語音合成前需要添加下面代碼。
    在applicationWillResignActive函數(shù)里
//  先注冊響應后臺控制
UIApplication.shared.beginReceivingRemoteControlEvents()

// 語音合成前需要添加

// 設置并激活音頻會話類別
do {
    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)
} catch {
    print(error.localizedDescription)
}
do {
    try AVAudioSession.sharedInstance().setActive(true)
} catch {
    print(error.localizedDescription)
}

// 語音合成在推送回調里調用的

// 調用API
SpeechManager.shared.speechWeather(with: alert as! String)
// 實現(xiàn)主要代碼
// 自定義語音播報方法
// 此處只例播報一個String的情況
    func speechWeather(with weather: String) {
        if let _ = speechUtterance {
            synthesizer.stopSpeaking(at: .immediate)
        }
        
        //播放聲音
        let path = Bundle.main.path(forResource: "sound", ofType: "wav")
        let pathURL = NSURL(fileURLWithPath: path!)
        do {
            audioPlayer = try AVAudioPlayer(contentsOf: pathURL as URL)
        } catch {
            audioPlayer = nil
        }
        audioPlayer?.delegate = self
        audioPlayer?.prepareToPlay()
        audioPlayer?.play()
        
        speechUtterance = AVSpeechUtterance(string: weather)
        //語音類型
        speechUtterance?.rate = 0.5
        synthesizer.speak(speechUtterance!)
    }
3. 遇到的問題早龟。

1.看似完成了app前臺和后臺的語音播報惫霸,但是app退到后臺手動殺掉進程就gg了。

2.還有審核時葱弟,由于開啟了background modes中的audio選項壹店。拒絕的原因是audio應用的場景不對,
審核被拒.png

二. 最重要的是Notification Service Extension(拓展推送服務)芝加。

1. 在項目中創(chuàng)建notificationservice, 選擇 file -> new -> target -> Notification Service Extension硅卢。
選擇NotificationService.jpeg
2. 點擊next。
  • product name: 拓展項目服務的名稱藏杖。
  • bundle identifier: 是原app項目的bundle identifier+拓展項目服務的名稱将塑。(原app的bundle identifier為com.test,拓展項目名稱為.myService蝌麸,則拓展項目的bundle identifier為com.test.myService)
    拓展工程.jpeg

創(chuàng)建完成在scheme中會多一個myService

WechatIMG7.jpeg

3.相關配置点寥。
  • 1 首先后端要給你個推送測試內容,內容模板如下:
    要記住在aps里一定要有"mutable -content"這個字段来吩,alert 這個用字符串就可以敢辩,不用字典。當然字典也行弟疆,后面可以獲取里面字符串也行
    后端配置.png
  • 2 在service工程里info.plist中添加App Transport Security Settings并且添加 Allow Arbitrary Loads為YES戚长。


    配置.jpeg
4.主要代碼如下。
//
//  NotificationService.swift
//  MyService
//
//  Created by JunQiang on 2018/5/24.
//  Copyright ? 2018年 多飛. All rights reserved.
//

import UserNotifications
import AVFoundation

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var bestAttemptContent: UNMutableNotificationContent?
    var audioPlayer: AVAudioPlayer?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.contentHandler = contentHandler
        bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
        
        if let bestAttemptContent = bestAttemptContent {
            // Modify the notification content here...
//            bestAttemptContent.title = "收款到賬"
            do {
                try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)
            } catch {
                print(error.localizedDescription)
            }
            do {
                try AVAudioSession.sharedInstance().setActive(true)
            } catch {
                print(error.localizedDescription)
            }
            //播放收金幣聲音
            bestAttemptContent.sound = UNNotificationSound.init(named: "sound.wav")

            //語音合成
            let aVSpeechSynthesizer = AVSpeechSynthesizer()
            let aps = bestAttemptContent.userInfo["aps"]
            let str = (aps as! NSDictionary)["alert"];

            let aVSpeechUtterance = AVSpeechUtterance(string: str as! String)
            aVSpeechUtterance.rate = AVSpeechUtteranceDefaultSpeechRate
            aVSpeechUtterance.voice = AVSpeechSynthesisVoice.init(language: "zh-CN")
            aVSpeechSynthesizer.speak(aVSpeechUtterance)
            
            contentHandler(bestAttemptContent)
        }
    }
    
    override func serviceExtensionTimeWillExpire() {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.

        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            contentHandler(bestAttemptContent)
        }
    }
}
4. 支持iOS10以上的手機怠苔,修改service中的target -> Deployment Target 選擇10.0同廉。
image.png

注意:播放收金幣的音頻時。
一開始考慮的是AVAudioPlayer播放本地音頻。后來發(fā)現(xiàn)只有第一次收到推送是有播放sound.wav恤溶,其他時候是有語音合成未有播放sound.wav乓诽。

//播放聲音
let path = Bundle.main.path(forResource: "sound", ofType: "wav")
let pathURL = NSURL(fileURLWithPath: path!)
do {
    audioPlayer = try AVAudioPlayer(contentsOf: pathURL as URL)
} catch {
   audioPlayer = nil
}
audioPlayer?.delegate = self
audioPlayer?.prepareToPlay()
audioPlayer?.play()

經(jīng)過一番搜索帜羊,才發(fā)現(xiàn)bestAttemptContent本身是可以播放音頻的咒程。改完發(fā)現(xiàn)可以了

//播放收金幣聲音
bestAttemptContent.sound = UNNotificationSound.init(named: "sound.wav")

到此結束,總結不好多多指教....謝謝

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末讼育,一起剝皮案震驚了整個濱河市帐姻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奶段,老刑警劉巖饥瓷,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異痹籍,居然都是意外死亡呢铆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門蹲缠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棺克,“玉大人,你說我怎么就攤上這事线定∧纫辏” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵斤讥,是天一觀的道長纱皆。 經(jīng)常有香客問我,道長芭商,這世上最難降的妖魔是什么派草? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮铛楣,結果婚禮上近迁,老公的妹妹穿的比我還像新娘。我一直安慰自己蛉艾,他們只是感情好钳踊,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勿侯,像睡著了一般拓瞪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上助琐,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天祭埂,我揣著相機與錄音,去河邊找鬼。 笑死蛆橡,一個胖子當著我的面吹牛舌界,可吹牛的內容都是我干的。 我是一名探鬼主播泰演,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼呻拌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了睦焕?” 一聲冷哼從身側響起藐握,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎垃喊,沒想到半個月后猾普,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡本谜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年初家,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乌助。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡溜在,死狀恐怖,靈堂內的尸體忽然破棺而出眷茁,到底是詐尸還是另有隱情炕泳,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布上祈,位于F島的核電站培遵,受9級特大地震影響,放射性物質發(fā)生泄漏登刺。R本人自食惡果不足惜籽腕,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纸俭。 院中可真熱鬧皇耗,春花似錦、人聲如沸揍很。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窒悔。三九已至呜袁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間简珠,已是汗流浹背阶界。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人膘融。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓芙粱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親氧映。 傳聞我的和親對象是個殘疾皇子春畔,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內容

  • 用到的組件 1、通過CocoaPods安裝 2屯耸、第三方類庫安裝 3拐迁、第三方服務 友盟社會化分享組件 友盟用戶反饋 ...
    SunnyLeong閱讀 14,615評論 1 180
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,111評論 25 707
  • 今天在家看了部心理學方面的舊片《催眠大師》蹭劈,想從以下兩個方面來探討著這部電影: 1疗绣、 為什么心理醫(yī)生徐瑞寧不能治療...
    水波兒閱讀 3,287評論 0 4
  • 導 語 我很有家庭責任感多矮,具體表現(xiàn)就是第一時間租房子和黃怡同居。當然哈打,我答應了黃怡的父母:“給我兩年塔逃,一定能夠賺到...
    飄雨桐V閱讀 282評論 1 1
  • 阿多尼斯說: "童年就是一座村莊,你永遠也走不出它的邊際"料仗。打小就一直呆在老家湾盗,小小的村莊是我世界的主體,但越長大...
    阿丁h閱讀 472評論 2 7