[iOS 10] Notification Content app extension による通知用のカスタムビューからオーディオファイルを再生する
はじめに
こんにちは。モバイルアプリサービス部の平屋です。
本シリーズ「iOS User Notifications UI framework」では、iOS 10 で新規追加された「User Notifications UI framework」の機能を使用した実装を紹介していきます。第 1 回目の記事で「Notification Content app extension」の基本事項を解説していますのであわせてご覧ください。
第 4 回目の本記事では Notification Content app extension による通知用のカスタムビューからオーディオファイルを再生する手順を解説します。
実現したいこと
本記事では、以下のスクリーンショットのようにカスタムビュー上に再生ボタンを配置し、再生ボタンをタップするとオーディオファイルを再生できるようにするための手順を解説していきます。
カスタムビューの制約
本記事で解説しようとしていることは、通知用のカスタムビュー上に単にボタンを置けば解決しそうに思えるかもしれません。しかし、通知用のカスタムビュー上にボタンを置いてもボタン自体は反応しません。カスタムビュー全体がタップに反応し、本体アプリへ遷移してしまいます。
UNNotificationContentExtension
の API Reference では以下のように説明されています。カスタムビュー上にタッチイベントを受け付けるコンポーネントを置いても、タッチイベントの伝達をシステムが妨げます。
The system prevents the delivery of touch events to your view controller while it is onscreen. Do not install gesture recognizers or rely on touch events in your interface.
UNNotificationContentExtension
には、メディア再生用のボタンを配置しタップイベントをハンドリングするための仕組みが用意されています。この仕組みの使い方を「再生ボタンを配置する」セクション以降で解説していきます。
再生ボタンを配置する
カスタムビュー上に再生ボタンを配置するには UNNotificationContentExtension
の mediaPlayPauseButtonType
, mediaPlayPauseButtonFrame
プロパティの getter を app extension の ViewController に追加します。
class NotificationViewController: UIViewController, UNNotificationContentExtension { // ... var mediaPlayPauseButtonFrame: CGRect { get { return CGRect(x: 20.0, y: 10.0, width: 30.0, height: 30.0) } } var mediaPlayPauseButtonType: UNNotificationContentExtensionMediaPlayPauseButtonType { get { return .overlay } } var mediaPlayPauseButtonTintColor: UIColor { get { return UIColor.darkGray } } // ... }
mediaPlayPauseButtonFrame
mediaPlayPauseButtonFrame
プロパティの getter では再生ボタンの frame を返します。
mediaPlayPauseButtonType
mediaPlayPauseButtonType
プロパティの getter では再生ボタンのタイプを返します。返り値の型は UNNotificationContentExtensionMediaPlayPauseButtonType
です。以下のいずれかの値を返すようにします。
- none
- default
- overlay
none
none
を返すと再生ボタンは表示されません。
default
default
を返すと、以下のスクリーンショットのようなスタンダードな再生ボタンが表示されます。
再生ボタンをタップすると、ボタンのアイコンが一時停止を表すアイコンに切り替わります。
overlay
overlay
を返すと、以下のスクリーンショットのような半透明の再生ボタンが表示されます。
再生ボタンをタップすると、ボタンが非表示になります。非表示になりますが、タップすることはできます。このタイプのボタンは、動画のサムネイル上にボタンを配置する場合に向いてそうです。
mediaPlayPauseButtonTintColor
ボタンの tintColor を指定したい場合は、mediaPlayPauseButtonTintColor
プロパティの getter を実装します。tintColor が反映されるのは mediaPlayPauseButtonType
が default
の場合のみのようです。
再生ボタンのタップイベントをハンドリングする
再生ボタンのタップイベントをハンドリングするには UNNotificationContentExtension
で定義されている mediaPlay()
, mediaPause()
メソッドを app extension の ViewController に追加します。ボタンタップ時に mediaPlay()
または mediaPause()
メソッドが呼ばれるようになります。
class NotificationViewController: UIViewController, UNNotificationContentExtension { // ... func mediaPlay() { // ... // 再生する処理 player.play() } func mediaPause() { // ... // 停止する処理 player.pause() } }
プレイヤーとオーディオファイルを準備する
app extension の ViewController の任意の場所にプレイヤーとオーディオファイルを準備するコードを追加します。
以下の実装例では、通知を受け取ったタイミングで通知からオーディオファイルを取り出し、AVFoundation
の AVAudioPlayer
を準備しています。
// ... import AVFoundation class NotificationViewController: UIViewController, UNNotificationContentExtension { // ... var player: AVAudioPlayer? // ... // MARK: - UNNotificationContentExtension func didReceive(_ notification: UNNotification) { // ... if let attachment = notification.request.content.attachments.first { if attachment.url.startAccessingSecurityScopedResource() { do { try self.player = AVAudioPlayer(contentsOf: attachment.url) } catch { print("prepare player error!") } attachment.url.stopAccessingSecurityScopedResource() } } } // ... }
さいごに
本記事では通知用のカスタムビューからオーディオファイルを再生する手順を解説しました。
今回はオーディオファイルの再生だけを扱いましたが、動画の再生なども今後試していきたいと思います。