Swift - 系统声音服务的使用(播放声音,提醒,震动)
作者:hangge | 2015-06-23 14:32
(本文代码已升级至Swift4)
1,系统声音服务介绍:
(2)提醒
(3)振动
4,声音或提醒播放完毕后的回调函数
默认情况下每触发一次声音提醒,系统就会执行一次。不管当前是否有其他的声音提醒未播放完毕。这样如果提醒声音时间比较长,在短时间内多次触发,那么就会造成重音(多个声音叠加在一起)。
我们可以设置个状态变量,播放前先根据它来判断是否要播放。同时使用 AudioServicesAddSystemSoundCompletion() 函数添加个声音播放完毕的回调。在开始播放、播放完毕中修改这个状态变量即可。
1,系统声音服务介绍:
系统声音服务提供了一个 Api,用于播放不超过 30 秒的声音。它支持的文件格式有限,具体的说只有 CAF、AIF 和使用 PCM 或 IMA/ADPCM 数据的 WAV 文件。
但此函数没有提供操作声音和控制音量的功能,因此如果是要为多媒体或游戏创建专门声音,就不要使用系统声音服务。

2,系统声音服务支持如下三种类型:
(1)声音:立刻播放一个简单的声音文件。如果手机静音,则用户什么也听不见。
(2)提醒:播放一个声音文件,如果手机设为静音或震动,则通过震动提醒用户。
(3)震动:震动手机,而不考虑其他设置。
3,使用样例(首先类中要引入AudioToolbox)
import AudioToolbox(1)声音播放
@IBAction func systemSound(_ sender: Any) {
//建立的SystemSoundID对象
var soundID:SystemSoundID = 0
//获取声音地址
let path = Bundle.main.path(forResource: "msg", ofType: "wav")
//地址转换
let baseURL = NSURL(fileURLWithPath: path!)
//赋值
AudioServicesCreateSystemSoundID(baseURL, &soundID)
//播放声音
AudioServicesPlaySystemSound(soundID)
}
(2)提醒
@IBAction func systemAlert(_ sender: Any) {
//建立的SystemSoundID对象
var soundID:SystemSoundID = 0
//获取声音地址
let path = Bundle.main.path(forResource: "msg", ofType: "wav")
//地址转换
let baseURL = NSURL(fileURLWithPath: path!)
//赋值
AudioServicesCreateSystemSoundID(baseURL, &soundID)
//提醒(同上面唯一的一个区别)
AudioServicesPlayAlertSound(soundID)
}
(3)振动
@IBAction func systemVibration(sender: AnyObject) {
//建立的SystemSoundID对象
let soundID = SystemSoundID(kSystemSoundID_Vibrate)
//振动
AudioServicesPlaySystemSound(soundID)
}
4,声音或提醒播放完毕后的回调函数
默认情况下每触发一次声音提醒,系统就会执行一次。不管当前是否有其他的声音提醒未播放完毕。这样如果提醒声音时间比较长,在短时间内多次触发,那么就会造成重音(多个声音叠加在一起)。
我们可以设置个状态变量,播放前先根据它来判断是否要播放。同时使用 AudioServicesAddSystemSoundCompletion() 函数添加个声音播放完毕的回调。在开始播放、播放完毕中修改这个状态变量即可。
import UIKit
import AudioToolbox
class ViewController: UIViewController {
//表示当前是否在播放
var isPlaying = false
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func btn(_ sender: Any) {
if !isPlaying {
//建立的SystemSoundID对象
var soundID:SystemSoundID = 0
//获取声音地址
let path = Bundle.main.path(forResource: "msg", ofType: "wav")
//地址转换
let baseURL = NSURL(fileURLWithPath: path!)
//赋值
AudioServicesCreateSystemSoundID(baseURL, &soundID)
//添加音频结束时的回调
let observer = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
AudioServicesAddSystemSoundCompletion(soundID, nil, nil, {
(soundID, inClientData) -> Void in
let mySelf = Unmanaged<ViewController>.fromOpaque(inClientData!)
.takeUnretainedValue()
mySelf.audioServicesPlaySystemSoundCompleted(soundID: soundID)
}, observer)
//播放声音
AudioServicesPlaySystemSound(soundID)
isPlaying = true
}
}
//音频结束时的回调
func audioServicesPlaySystemSoundCompleted(soundID: SystemSoundID) {
print("Completion")
isPlaying = false
AudioServicesRemoveSystemSoundCompletion(soundID)
AudioServicesDisposeSystemSoundID(soundID)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
全部评论(9)
站长你好:
这一句始终报错,望指点迷津
AudioServicesAddSystemSoundCompletion(soundID, nil, nil, proc,
UnsafeMutablePointer(unsafeAddressOf(self)))
错误提示:
Cannot invoke initializer for type 'UnsafeMutablePointer<_>' with an argument list of type '(UnsafeRawPointer)'
站长回复:文章代码现已更新,你可以再看下。
站长,我想问下有没有播放字符串的框架啊(不传url传的是字符串,传什么播放什么)
站长回复:不太确定你的意思。你是指将字符串文本朗读出来吗?
謝謝站長花時間寫教學並且分享
感恩囉^^
站长回复:不客气,欢迎常来看看:)
模拟器有声音,真机没有声音是什么问题..
站长回复:是不是因为你手机静音了。我试了下真机是没问题的。
站长你好,如果不断的触发系统声音,提醒等播放按钮,会出现重音,怎么判断系统声音播放完毕呢?
站长回复:AudioServicesAddSystemSoundCompletion()方法可以实现,我在文章的最后写了个样例,你可以参考下。
AudioServicesCreateSystemSoundID(baseURL, &soundID)
soudID 有错误,求解
cannot convert value of type 'SystemSoundID'(aka 'Uint32'')
站长回复:soundID要使用var定义,文章已修改。
嗯,感谢站长回复。可能是我没有设置好。
WARNING: 998: Failure to setup sound, err = -50
上面是错误信息
下面是代码
button_Shake.addTarget(self, action: Selector("systemVibration"), forControlEvents: UIControlEvents.TouchUpInside)
func systemVibration() {
let soundID = SystemSoundID(kSystemSoundID_Vibrate)
AudioServicesPlaySystemSound(soundID)
}
直接写的。是不是在模拟器上不能运行啊,我在模拟器上运行的。
站长回复:是的,震动必须使用真机测试。你写的代码是没问题的。
点震动报错
2015-12-13 12:41:45.239 test[2173:101795] -[test.Audio_1 systemVibration]: unrecognized selector sent to instance 0x7fabda522620
2015-12-13 12:41:45.245 test[2173:101795] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[test.Audio_1 systemVibration]: unrecognized selector sent to instance 0x7fabda522620'
*** First throw call stack:
站长回复:测试了下代码没问题呀。你试试看把震动的两行代码注释掉看还会不会报错,看错误信息像是响应事件有问题
很感谢
站长回复:不客气^_^