国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

iOS開發微信收款到賬語音提醒功能思路詳解

2019-10-21 18:44:47
字體:
來源:轉載
供稿:網友

一、背景

為了解決小商戶老板們在頻繁交易中不方便核對、確認到賬的痛點,產品MM提出了新版本需要支持收款到賬語音提醒功能。這篇文章總結了開發過程中遇到的坑和一些小技巧。

二、技術方案

后臺喚醒App

收款到賬語音提醒需要收款方在收到款后,播放一段TTS合成語音播報金額,微信在前臺時可以通過模板消息將需要播報的金額帶下來,再請求TTS數據并播放,但是app在掛起或者被kill掉的情況下要如何請求語音數據并播放呢?

iOS提供了兩種方式喚醒處于掛起或已經被kill掉的app。分別是Silent Notification和VoIP Push Notification,客戶端在被喚醒之后將獲得30s的后臺運行時間,這段運行時間足以請求合成語音數據并播放。

1.Silent Notification:

Silent Notification在iOS7以上便可以支持,但是每小時能推送的Silent Notification次數有限制。

2.VoIP Push Notification

VoIP Push Notification則是在iOS8以上才支持的新Push類型,相比于Silent Notification,VoIP Push具有高優先級、低延遲的優勢,并且沒有次數限制。
對比這兩種技術方案,VoIP Push Notification明顯更適合用于收款到賬語音提醒的喚醒方案。

TTS合成語音

TTS語音合成方案分為離線合成方案和在線合成方案,離線合成方案省去網絡請求,合成速度更快,節省網絡流量,但是合成音的聽起來比較機械,語速和停頓的處理較差一些。如果對合成音的效果要求不是特別高,可以考慮采用iOS自帶的AVSpeechSynthesis框架,免去語音庫的合入,減少安裝包大小。

在線合成方案的效果則相對更像人聲,富有感情。考慮到產品體驗,我們采用了搜索產品部提供的在線語音合成方案,接入方式可以看這篇文章。合成音格式支持wav,mp3,silk,amr,speex,對比后發現,在合成相同文本的情況下,amr的壓縮率最高,但是能聽到音質下降明顯。silk格式壓縮率次高,且能保持相對清晰的音質,單條合成語音大小在2KB左右。

喚醒后播放音頻文件

在請求到合成語音后,要在后臺或者鎖屏狀態下播放音頻文件,AVAudio Session的Category值需要使用AVAudioSessionCategoryPlayback或是AVAudioSessionCategoryPlayAndRecord,CategoryOptions根據實際需要可選擇MixWithOthers(與其他聲音混音)或是DuckOthers(調低其他聲音的音量)。

ios,微信到賬語音提醒,微信收款到賬語音提醒

需要注意的是,只有iOS10以上才支持app被喚醒后在后臺/鎖屏狀態下播放音頻。所以iOS10以下的設備,在收到VoIP Push后只能在local push上設定一段固定鈴聲,這也是為什么iOS10以下只有“微信支付收款到賬”,而沒有后面具體的金額數值。

三、靜音開關檢測

不幸的是,在產品發布后沒多久就受到了某互聯網大佬的吐槽。

ios,微信到賬語音提醒,微信收款到賬語音提醒

從產品體驗上來說,收款到賬的金額播報是隨著local push的彈出一起播放的,更像是一種特殊的push鈴聲,而蘋果對push鈴聲的處理是受到靜音開關控制的,所以講道理,這個吐槽是合理的。然而前面提到App在被VoIP Push喚醒之后,需要將AudioSessionCategory設置為AVAudioSessionCategoryPlayback或AVAudioSessionCategoryPlayAndRecord才可以在后臺播放音頻文件,這兩種模式是不受靜音開關控制的。要實現這個需求,就必須獲取當前靜音開關的狀態。而蘋果在iOS5之后并沒有明確地提供一種方式讓開發獲取靜音開關的狀態,這就陷入了一個尷尬的局面。

蘋果在iOS5之前可以使用以下方式監聽靜音鍵開關

- (BOOL)isMuted {  CFStringRef route;  UInt32 routeSize = sizeof(CFStringRef);  OSStatus status = AudioSessionGetProperty(kAudioSessionProperty_AudioRoute, &routeSize, &route);  if (status == kAudioSessionNoError)  {   if (route == NULL || !CFStringGetLength(route))    return YES;  }  return NO; }

蘋果在iOS5之后便禁止了使用這種方式監聽靜音按鍵,背后的原因應該是蘋果希望開發者使用AVAudioSession來提供統一的音頻播放效果。

最后我在Reddit上找到了一種曲線救國的方式,實現起來也不復雜:使用AudioServicesPlaySystemSound播放一段0.2s的空白音頻,并監聽音頻播放完成事件,如果從開始播放到回調完成方法的間隔時間小于0.1s,則意味當前靜音開關為開啟狀態。

void SoundMuteNotificationCompletionProc(SystemSoundID ssID,void* clientData){ MMSoundSwitchDetector* detecotr = (__bridge MMSoundSwitchDetector*)clientData; [detecotr complete];}- (instancetype)init { self = [super init]; if (self) {  NSURL *pathURL = [[NSBundle mainBundle] URLForResource:@"mute" withExtension:@"caf"];  if (AudioServicesCreateSystemSoundID((__bridge CFURLRef)pathURL, &_soundId) == kAudioServicesNoError){   AudioServicesAddSystemSoundCompletion(self.soundId, CFRunLoopGetMain(), kCFRunLoopDefaultMode, SoundMuteNotificationCompletionProc,(__bridge void *)(self));   UInt32 yes = 1;   AudioServicesSetProperty(kAudioServicesPropertyIsUISound, sizeof(_soundId),&_soundId,sizeof(yes), &yes);  } else {   MMErrorWithModule(LOGMODULE, @"Create Sound Error.");   _soundId = 0;  } } return self;}- (void)checkSoundSwitchStatus:(CheckSwitchStatusCompleteBlk)completHandler { if (self.soundId == 0) {  completHandler(YES);  return; } self.completeHandler = completHandler; self.beginTime = CACurrentMediaTime(); AudioServicesPlaySystemSound(self.soundId);}- (void)complete { CFTimeInterval elapsed = CACurrentMediaTime() - self.beginTime; BOOL isSwitchOn = elapsed > 0.1; if (self.completeHandler) {  self.completeHandler(isSwitchOn); }}

四、設置聲音閾值

另外一個用戶反饋較多的問題是聽不到播報聲音,通過查看日志發現是觸發語音播報時,用戶設置的系統音量過小所導致。首先想到的解決方案是直接設置AVAudioPlayer的volume(或者是AudioQueue中的kAudioQueueParam_Volume),然而實驗過后發現這樣行不通,volume屬性受制于系統音量(比如系統volume是0.5,AVAudioPlayer的音量是0.6,則最終的音量為0.5*0.6 =0.3)。要解決音量過小的問題,還是需要通過調節系統音量。最終的解決方案借鑒了進入收付款展示二維碼時自動調節屏幕亮度的方案:如果屏幕亮度未達到閾值,則調高屏幕亮度到閾值,離開頁面時,將亮度設回原亮度。同理,播放提示音時,若用戶設置的系統音量小于閾值,則調節到閾值。提示音播放完畢后,將提示音調回原音量。

控制系統音量有兩種方式:

方式一:通過MPMusicPlayerController設置音量

MPMusicPlayerController *mpc = [MPMusicPlayerController applicationMusicPlayer];//This property is deprecated -- use MPVolumeView for volume control instead.mpc.volume = 0; //0.0~1.0

第一種方式簡單粗暴,在設置的時候會彈出系統音量提示框,如果用戶在使用app的過程突然彈出音量框,會對用戶造成困擾,不建議使用這種方式,并且蘋果在iOS7.0以后已將該屬性標為deprecated。

方式二:通過MPVolumeView設置音量

第二種方式則是將一個看不見的MPVolumeView添加到當前視圖上,系統音量提示框就不會顯示了

需要注意的是,在調節完系統音量需要將MPVolumeView移除,否則后續用戶手動調節音量會出現系統音量提示框不顯示的情況。

調節音量的方式,則是先取到MPVolumeView中名為MPVolumeSlider的子View,并對其發送模擬用戶操作的事件。

- (void)setSystemVolume:(float)volume { UISlider* volumeViewSlider = nil; for (UIView *view in [self.m_privateVoulmeView subviews]){  if ([view.class.description isEqualToString:@"MPVolumeSlider"]){   volumeViewSlider = (UISlider*)view;   break;  } } if (volumeViewSlider != nil) {  [volumeViewSlider setValue:volume animated:NO];  //通過send  [volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside]; }}

總結

以上所述是小編給大家介紹的iOS開發微信收款到賬語音提醒功能思路詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VEVB武林網網站的支持!


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 霍林郭勒市| 皮山县| 丹棱县| 镇远县| 夏津县| 长丰县| 新沂市| 宜兰市| 霞浦县| 蒙山县| 隆回县| 天气| 明溪县| 桃江县| 新晃| 乌拉特前旗| 尼木县| 盐边县| 射洪县| 邳州市| 商丘市| 梅河口市| 玉田县| 盐亭县| 西林县| 托克托县| 彰化县| 滦南县| 中阳县| 泉州市| 常熟市| 承德市| 荣成市| 开封县| 大港区| 黄龙县| 霍林郭勒市| 仁寿县| 仁布县| 中西区| 新河县|