Help us understand the problem. What is going on with this article?

ローカル通知の音を動的に変更する(iOS10以降)

ローカル通知の着信音をカスタマイズしたいんだけど、っていうニーズはまさにFAQで、stackoverflowなんかにもたくさんあがっています。

Choose custom sound for local notifications

iOS9以前では、UILocalNotificationsoundNameプロパティにメインバンドルに含まれる.cafファイルの名前を指定すればその音を鳴らせるようになっていました。逆に言うと、あらかじめバンドルに入れてビルドした音声ファイルしか通知を受信したときに鳴らすことが出来ませんでした。

iOS10ではUILocalNotificationはdeprecatedとなり、新たにUNNotificationRequestUNNotificationContentを使って通知を送ることが推奨されるようになりました。

概要は下記の記事などを参照下さい。

iOS 10以降のNotificationの基本

UNNotificationContentには、UNNotificationSound型のsoundというプロパティが追加されています。

このUNNotificationSoundの、init(named:)コンストラクタのnamedパラメータの説明に、

The name of the sound file to play. This file must be located in the current executable’s main bundle or in the 
Library/Sounds directory of the current app container directory. This parameter must not be nil.

とあり、iOS10からは従来のメインバンドルだけでなく、Library/Soundsの下に置いたファイル名を指定できるようになりました。

レアケースなんですけど、インハウスの業務用向けアプリの開発で、特殊な環境の現場で使うので、どんな通知音が聞き取りやすいかは現場で使ってもらわないと選べないから、通知の音はシステムの効果音のなかから、後で任意に選べるようにして欲しいというオーダーがありました。

システム効果音は、 /System/Library/Audio/UISoundsなどの中に納められているので、ローカル通知を送る前にこれらのファイルを選んで、<App>/Library/Soundsにコピーしておくことで、システム効果音をならすことが出来ました。

通常、アプリケーションのLibraryの下にSoundsディレクトリはないので、作成します。

参考:File System Basics:About the iOS File System

// <App>/Library/Soundsが無ければ作成
let libraryUrl = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask)[0]
let soundDirUrl = libraryUrl.appendingPathComponent("Sounds")
try? FileManager.default.createDirectory(at: soundDirUrl, withIntermediateDirectories: true, attributes: nil)

Library/Soundsの下に効果音ファイルを置きます。

// あらかじめリストアップしておいたファイルから選んで${App}/Library/Soundsにコピー
do {
        let from =  URL(fileURLWithPath:"/System/Library/Audio/UISounds/Modern").appendingPathComponent("calendar_alert_chord.caf")
        let dest = soundDirUrl.appendingPathComponent(file)
        try FileManager.default.copyItem(at: from, to: dest)
}catch{
        log.error(error)
        return false
}
return true

UNNotificationSoundに先ほどコピーした"calendar_alert_chord.caf"を指定して、ローカル通知を送ります。

 let content = UNMutableNotificationContent()
 content.title = ".."
 content.subtitle = "..."
 content.body = ".."
 content.userInfo = [...]

 content.sound = UNNotificationSound(named:"calendar_alert_chord.caf")

 let request = UNNotificationRequest.init(identifier: UUID().uuidString, content: content, trigger: nil)

 let center = UNUserNotificationCenter.current()
 center.add(request)

以上です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした