网上有很多博客说添加IOS10之后新增的Notification Service Extension才可以推送Apns自定义铃声,实际上是不对的,简单的自定义语音推送IOS10之前就已经支持,而且APNS Server与deviceToken直接相关联,自然也不存在许多博客说的杀死App后接受不到推送的问题。
有关Notification Service Extension多媒体拓展问题可参考https://www.jianshu.com/p/56c91be16c3d
本文提供简单的自定义语音推送解决方案。
修改苹果原生推送声音:
(1)App在后台或者被杀死时,服务器给你推送的userinfo中sound字段的value和你本地的声音文件名一致时,这样就可以播放你本地自定义的语音文件(mp3,wav等常见语音格式都可以支持)。
(2)App运行在前台时大部分App会关闭掉UNNotificationPresentationOptionSound权限,当你有类似美团接单,支付宝到账等需前台响铃的需求时需要自己写响铃方法,这里主要有两种解决方案。
方案1播放系统音效
/// 播放通知铃声
- (void)jyeb_playSoundWithFilename:(NSString *)filename fileExtension:(NSString *)fileExtension {
// 系统值 kSystemSoundID_Vibrate = 0x00000FFF
SystemSoundID sound = 1;
// 转换 URL
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:filename ofType:fileExtension];
NSURL *soundURL = [NSURL fileURLWithPath:soundFilePath];
// 生成系统音效id
AudioServicesCreateSystemSoundID((__bridge CFURLRef)soundURL, &sound);
// 播放系统音效
AudioServicesPlaySystemSound(sound);
}
将此方法在应用在前台处理推送的方法中调用,注意区分iOS10前后处理方法的不同。
方案2:AVAudioPlayer播放
单例一个AVAudioPlayer控制类
/// 播放音频
- (void)playWithContentsOfFileName:(NSString *)fileName fileType:(NSString *)fileType callBack:(EBAPNsAudioCompleted)callBack
{
self.callBack = callBack;
[self activePlayback];
// 调节音量
[self setHighVolume];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:fileName ofType:fileType];
NSURL *soundURL = [NSURL fileURLWithPath:soundFilePath];
self.audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:soundURL error:nil];
self.audioPlayer.delegate = self;
// 开始播放
[self.audioPlayer prepareToPlay] ;
[self.audioPlayer play];
}
// 播放器激活
- (void)activePlayback
{
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:NULL];
[[AVAudioSession sharedInstance] setActive:YES error:NULL];
}
// 播放器休眠
- (void)disactivePlayback
{
[[AVAudioSession sharedInstance] setActive:NO error:NULL];
}
// 播放完成
- (void) playCompleted
{
if (self.callBack) {
self.callBack() ;
}
}
#pragma mark - AVAudioPlayerDelegate
// 播放结束回调
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
// 设置回初始音量
[self setNormalVolume] ;
[self disactivePlayback] ;
[self performSelectorOnMainThread:@selector(playCompleted) withObject:nil waitUntilDone:NO] ;
}
这里我们推荐使用第一种方法,通过系统方法进行播放。