[iOS 10] Notification Content app extension による通知用のカスタムビューからオーディオファイルを再生する

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは。モバイルアプリサービス部の平屋です。

本シリーズ「iOS User Notifications UI framework」では、iOS 10 で新規追加された「User Notifications UI framework」の機能を使用した実装を紹介していきます。第 1 回目の記事で「Notification Content app extension」の基本事項を解説していますのであわせてご覧ください。

第 4 回目の本記事では Notification Content app extension による通知用のカスタムビューからオーディオファイルを再生する手順を解説します。

実現したいこと

本記事では、以下のスクリーンショットのようにカスタムビュー上に再生ボタンを配置し、再生ボタンをタップするとオーディオファイルを再生できるようにするための手順を解説していきます。

user-notifications-ui-framework-4-1

カスタムビューの制約

本記事で解説しようとしていることは、通知用のカスタムビュー上に単にボタンを置けば解決しそうに思えるかもしれません。しかし、通知用のカスタムビュー上にボタンを置いてもボタン自体は反応しません。カスタムビュー全体がタップに反応し、本体アプリへ遷移してしまいます。

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 には、メディア再生用のボタンを配置しタップイベントをハンドリングするための仕組みが用意されています。この仕組みの使い方を「再生ボタンを配置する」セクション以降で解説していきます。

再生ボタンを配置する

カスタムビュー上に再生ボタンを配置するには UNNotificationContentExtensionmediaPlayPauseButtonType, 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 を返すと、以下のスクリーンショットのようなスタンダードな再生ボタンが表示されます。

user-notifications-ui-framework-4-1

再生ボタンをタップすると、ボタンのアイコンが一時停止を表すアイコンに切り替わります。

user-notifications-ui-framework-4-2

overlay

overlay を返すと、以下のスクリーンショットのような半透明の再生ボタンが表示されます。

user-notifications-ui-framework-4-3

再生ボタンをタップすると、ボタンが非表示になります。非表示になりますが、タップすることはできます。このタイプのボタンは、動画のサムネイル上にボタンを配置する場合に向いてそうです。

user-notifications-ui-framework-4-4

mediaPlayPauseButtonTintColor

ボタンの tintColor を指定したい場合は、mediaPlayPauseButtonTintColor プロパティの getter を実装します。tintColor が反映されるのは mediaPlayPauseButtonTypedefault の場合のみのようです。

再生ボタンのタップイベントをハンドリングする

再生ボタンのタップイベントをハンドリングするには UNNotificationContentExtension で定義されている mediaPlay(), mediaPause() メソッドを app extension の ViewController に追加します。ボタンタップ時に mediaPlay() または mediaPause() メソッドが呼ばれるようになります。

class NotificationViewController: UIViewController, UNNotificationContentExtension {

    // ...

    func mediaPlay() {
        // ...

        // 再生する処理
        player.play()
    }

    func mediaPause() {
        // ...

        // 停止する処理
        player.pause()
    }
}

プレイヤーとオーディオファイルを準備する

app extension の ViewController の任意の場所にプレイヤーとオーディオファイルを準備するコードを追加します。

以下の実装例では、通知を受け取ったタイミングで通知からオーディオファイルを取り出し、AVFoundationAVAudioPlayer を準備しています。

// ...

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()
            }
        }
    }

    // ...
}

さいごに

本記事では通知用のカスタムビューからオーディオファイルを再生する手順を解説しました。

今回はオーディオファイルの再生だけを扱いましたが、動画の再生なども今後試していきたいと思います。

参考資料