見出し画像

WidgetKitでミニピアノウィジェットを作ってみた

WidgetKitとBackground Modeを組み合わせて、ミニピアノウィジェットを作ってみた。


Widgetの外観


ウィジェット上部に鍵盤を有効化させるボタンを1つと、鍵盤を表すViewを横向きに7つ配置したシンプルな外観。

Background Mode

アプリがバックグラウンド状態の時でも、音源を再生することができるように、Background Modeをオンにする必要がある。「Signing & Capabilities」からBackground Modeを選択して、プロジェクトにBackground Modeを追加する。

「Audio, AirPlay, and Picture」にチェックを入れると、アプリがバックグラウンド状態でも、ウィジェット上で音源を再生することができるようになる。

音源の入手

フリーで提供くださっている「ド」、「レ」、「ミ」、「ファ」、「ソ」、「ラ」、「シ」の音源素材を入手する。
今回は以下のページの音源をお借りした。
https://maou.audio/category/se/se-inst/

App Intent

iOS 17から、App Intentを使用することで、ウィジェットにインタラクティブな
ボタンを配置することができるようになった。

鍵盤ボタンをタップした時に実行するIntent

鍵盤をタップした時に音源が再生するIntentを作成する。例えば、鍵盤をタップした時に「ド」が鳴るようなIntentは以下のようになる。

struct DoIntent: AudioPlaybackIntent {
    static var title: LocalizedStringResource = "Do Intent"
    static var openAppWhenRun: Bool = false
    
    func perform()  throws -> some IntentResult {
        var player: AVAudioPlayer?
        if let sound = NSDataAsset(name: "ド") {
            player = try? AVAudioPlayer(data: sound.data)
            player?.volume = 0.1
            player?.play()
            sleep(1)
        }
        return .result()
    }
}

AVAudioPlayer のplay() 実行後にsleep() で1秒待機させて、音源が最後まで流れきるようにしておく。
同様に、「レ」、「ミ」、「ファ」、「ソ」、「ラ」、「シ」の音源を再生するIntentを作成する。

電源ボタンをタップした時に実行するIntent

アプリがバックグラウンド状態でも、音源の再生を行うことができるように、音源再生設定を行うIntentを作成する。

struct SoundOnIntent: AppIntent {
    static var title: LocalizedStringResource = "Sound On Intent"
    static var openAppWhenRun: Bool = false
    
    func perform() async throws -> some IntentResult {
        do {
            let session = AVAudioSession.sharedInstance()
            do {
                try session.setCategory(.playback, mode: .default)
            } catch  {
                fatalError()
            }
        }
        return .result()
    }
}

完成したアプリ

雑感

ウィジェットのボタンを連打してしまうと、アプリが立ち上がってしまうので、正直使い勝手は悪い。ウィジェット単独で音源を再生する技術は、アプリ化するネタ技術として使えるかもしれない。

最後まで記事をお読みいただきありがとうございます! 記事が参考になればフォロー・♥いただけると凄く励みになります🥳