LoginSignup
54
53

More than 5 years have passed since last update.

watchOS 3 で「アレ」は本当にできるようになったのか?

Posted at
1 / 46

自己紹介

  • フリーランスiOSエンジニア
  • iOS / watchOS Sampler シリーズをつくっています

Screen Shot 2016-06-04 at 16.41.53.png


2015年にお手伝いしたwatchOS案件

(一部だけお手伝い、非公開プロジェクトも含む)


「それ、残念ながらできないんです・・・」

(企画の詳細は書けませんが・・・)

  • ジャイロが必要な機能 × 2
  • アプリが非アクティブになってもセンサの値を取り続ける必要がある機能 × 2
  • タップ位置を知る必要があるインタラクション × ?
  • ジョイスティック的な引っ張る系のUI × 2
  • ウォッチ本体から音を鳴らす × ?

watchOS 3 ではできるようになった!

  • ジャイロが必要な機能 - Gyroscope access
  • アプリが非アクティブになってもセンサの値を取り続ける必要がある機能 - Background support
  • タップ位置を知る必要があるインタラクション - UITapGestureRecognizer
  • ジョイスティック的な引っ張る系のUI - UIPanGestureRecognizer
  • ウォッチ本体から音を鳴らす - Speaker Audio

(参考:API Diffsから見る watchOS 3 の新機能 - Qiita


本当にできるようになったのか?

  • キーノート、あるいはドキュメントで見かけただけ
  • 実際に試してみないと思わぬ制限があるかもしれない

watchOS 3 を入れた Apple Watch 実機で「本当にできるようになったのか」試してみる


検証1: Gyroscope access


API自体は前からあった

watchOS-2-Samplerのコード
let motionManager = CMMotionManager()

override func willActivate() {
    super.willActivate()

    let handler:CMGyroHandler = {(data: CMGyroData?, error: NSError?) -> Void in
        // データ取得時の処理
    }

    if motionManager.isGyroAvailable {
        motionManager.startGyroUpdates(to: OperationQueue.current()!, withHandler: handler)
    } else {
        // 利用不可の場合の処理
    }
}

が、

motionManager.isGyroAvailable の戻り値が常に false だった。

事実上の非サポート だった


WWDC16のキーノート

Screen_Shot_2016-07-01_at_01_21_46.png

はっきり "Gyroscope Access" と書かれている


watchOS 3 実機で試してみた

print("\(CMMotionManager().isGyroAvailable)")


実行結果


false


→ watchOS 3 でも CMGyroData は Not Available!!!!


????

Screen_Shot_2016-07-01_at_01_21_46.png

そんなはずは・・・


WWDC16のwatchOS関連セッションスライドを"gyro"で検索

  • What's New in watchOS 3
  • Architecting for Performance on watchOS 3
  • Building Great Workout Apps
  • Keeping Your Watch App Up to Date
  • Quick Interaction Techniques for watchOS
  • Designing Great Apple Watch Experiences
  • Game Technologies for Apple Watch

出てこない・・・


思わぬ伏兵


Health and Fitness with Core Motion (713)


Screen Shot 2016-07-01 at 02.24.46.png

スライドp49、動画では13分ぐらいから。


Screen_Shot_2016-07-01_at_02_24_46.png

CMDeviceMotion が Apple Watch で利用可能!


これが取れるならむしろ CMGyroData はいらない


CMDeviceMotion から得られるデータ


デバイスの角加速度

public var rotationRate: CMRotationRate { get }

Screen Shot 2016-07-01 at 11.07.20.png

  • 回転の加速度
  • ジャイロセンサより得られる
  • 大昔に試したことがあるが、CMGyroDataとほぼ同じ値 (小数点第2位ぐらいまで一致)が得られた

利用例:モーション検出

CMDeviceMotionから得られる 姿勢情報/オイラー角(加速度センサとジャイロから求められる) を利用して、テニスのフォアハンドとバックハンドのスウィングを自動検出

Screen Shot 2016-07-01 at 11.10.45.png

  • 同セッションでサンプルが紹介されている
  • どこかで話すか解説記事を書きます

API自体は前からあった

watchOS-2-Samplerのコード
let motionManager = CMMotionManager()

override func willActivate() {
    super.willActivate()

    let handler: CMDeviceMotionHandler = {(motion: CMDeviceMotion?, error: NSError?) -> Void in
        // データ取得時の処理
    }

    if motionManager.isDeviceMotionAvailable {
        motionManager.startDeviceMotionUpdates(to: OperationQueue.current()!, withHandler: handler)
    } else {
        // 利用不可の場合の処理
    }
}

motionManager.isDeviceMotionAvailable が必ず false を返してきていた


watchOS 3 実機で試してみた


(デモ)


検証1: Gyroscope access → watchOS 3 では可能!


検証2: ウォッチ本体から音を鳴らす


watchOS 2 からある WKAudioFilePlayer

  • オーディオファイルを再生するクラス
  • 要Bluetoothヘッドセット

Bluetooth ヘッドセットを「Apple Watchに」ペアリングして音を聴く!?


WWDC16のキーノート

Screen_Shot_2016-07-01_at_10_28_46.png

Apple Watch のスピーカーから音を出せるようになった?


AV Foundation on watchOS


  • watchOS 3 から AVFoudation が使えるように!
  • 全部のクラスが移行されるわけではないが、色々入っている
    • AVAudioPlayerNode(オーディオファイル再生)
    • AVAudioEngine(オーディオ処理諸々)
    • AVSpeechSynthesizer(音声合成) 等々

(参考:API Diffsから見る watchOS 3 の新機能 - Qiita


watchOS 3 実機で試してみた


iOS-9-Samplerのコードを流用
import Foundation
import AVFoundation

struct AudioEngine {
    private let engine = AVAudioEngine()
    private let player = AVAudioPlayerNode()
    private var file: AVAudioFile?

    init() {
        setup()
    }

    private mutating func setup() {
        // setup engine and player
        engine.attach(player)
        guard let fileURL = Bundle.main().urlForResource("drumLoop", withExtension: "caf") else {
            fatalError("\"drumLoop.caf\" file not found.")
        }
        do {
            let file = try AVAudioFile(forReading: fileURL)
            self.file = file
            engine.connect(player, to: engine.mainMixerNode, format: file.processingFormat)
        }
        catch {
            fatalError("Could not create AVAudioFile instance. error: \(error).")
        }
    }

    private func scheduleLoop() {
        guard let file = file else {
            fatalError("`file` must not be nil in \(#function).")
        }

        player.scheduleFile(file, at: nil) {
            self.scheduleLoop()
        }
    }

    // MARK: - Public

    func start() {
        // Schedule buffers on the player.
        scheduleLoop()

        // Start the engine.
        do {
            try engine.start()
        }
        catch {
            fatalError("Could not start engine. error: \(error).")
        }
        player.play()
    }

    // Stop the engine
    func stop() {
        player.stop()
        engine.stop()        
    }

    func isPlaying() -> Bool {
        return player.isPlaying
    }
}

(デモ)


検証2: ウォッチ本体から音を鳴らす → watchOS 3 では可能!


ここまでのまとめ


watchOS 3 では

CMDeviceMotionでジャイロセンサの値、およびそれを利用した姿勢情報を取れるようになった!

→ ⌚️を利用したモーション認識が可能に!


watchOS 3 では

AVAudioEngineが使えるようになった!

→ ⌚️から「直接」音を出せるようになった!


次回予定:

  • バックグラウンド機能の検証
    • CPU負荷とか、いろいろ制約はあるっぽい

ご清聴ありがとうございました!


本記事は、2016.7.1に開催された WWDC.next でのLT資料です。

※Appleによる公開リソースをもとに作成しています。

54
53
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
54
53