I solved this by copying a system sound file to ~/Library/Sounds directory and name it as notification.caf. The server alert payload specify this as the name of the sound to be played. Whenever the user selects another sound, that sound will be copied to the same folder and overwrites the old sound.
Payload:
{
"aps": {
"sound": "notification.caf"
}
}
// get the list of system sounds, there are other sounds in folders beside /New
let soundPath = "/System/Library/Audio/UISounds/New"
func getSoundList() -> [String] {
var result:[String] = []
let fileManager = NSFileManager.defaultManager()
let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(soundPath)!
for url in enumerator.allObjects {
let string = url as! String
let newString = string.stringByReplacingOccurrencesOfString(".caf", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
result.append(newString)
}
return result
}
// copy sound file to /Library/Sounds directory, it will be auto detect and played when a push notification arrive
class func copyFileToDirectory(fromPath:String, fileName:String) {
let fileManager = NSFileManager.defaultManager()
do {
let libraryDir = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.LibraryDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let directoryPath = "(libraryDir.first!)/Sounds"
try fileManager.createDirectoryAtPath(directoryPath, withIntermediateDirectories: true, attributes: nil)
let systemSoundPath = "(fromPath)/(fileName)"
let notificationSoundPath = "(directoryPath)/notification.caf"
let fileExist = fileManager.fileExistsAtPath(notificationSoundPath)
if (fileExist) {
try fileManager.removeItemAtPath(notificationSoundPath)
}
try fileManager.copyItemAtPath(systemSoundPath, toPath: notificationSoundPath)
}
catch let error as NSError {
print("Error: (error)")
}
}
The push notification sound can be buggy though, I have to reboot my phone before the sound will play reliably for every notification.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…