iOS13+のSafariでdevicemotionやdeviceorientationイベントの許可を取得する方法


iOS 13〜 の モバイル Safari では、端末の傾きや加速度などの情報を提供する DeviceMotionEvent や DeviceOrientationEvent を取得する際、ユーザーの許可が必要になりました。

実装に少し手間取ったのでまとめておきます。

注意点

HTTPSであること

HTTPS通信であることが求められます。
開発環境の準備が面倒な場合は、Chromeで開発を進めるといいかもしれません。

ユーザーのアクションが必要

ページ表示直後にいきなり許可を取得することはできません。
ボタンなどを設置してユーザーにクリックしてもらってonClickなどを発火させてから許可を得る必要があります。

iOS 12.2 ではこの方法は使えない

iOS 12.2 ではユーザーがSafariの設定を変更しない限りイベントを取得できないという悲しい仕様です。

設定 > Safari > 「モーションと画面の向きのアクセス」の設定項目が追加されており、デフォルトでOFFになっています。

そのため iOS 12.2 では、ユーザーにこの設定をONに変えてもらうほかに devicemotion や deviceorientation イベントを取得する方法はありません。

コード

DeviceMotionEvent 用のコード

sample.js
const requestDeviceMotionPermission = () => {
  if (
    DeviceMotionEvent &&
    typeof DeviceMotionEvent.requestPermission === 'function'
  ) {
    // iOS 13+ の Safari
    // 許可を取得
    DeviceMotionEvent.requestPermission()
    .then(permissionState => {
      if (permissionState === 'granted') {
        // 許可を得られた場合、devicemotionをイベントリスナーに追加
        window.addEventListener('devicemotion', e => {
          // devicemotionのイベント処理
        }
      } else {
        // 許可を得られなかった場合の処理
      }
    })
    .catch(console.error) // https通信でない場合などで許可を取得できなかった場合
  } else {
    // 上記以外のブラウザ
  }
}

// ボタンクリックでrequestDeviceMotionPermission実行
const startButton = document.getElementById("start-button")
startButton.addEventListener('click', requestDeviceMotionPermission, false)

DeviceOrientationEvent 用のコード

上記の devicemotion 用のコードと同様です。

sample.js
const requestDeviceOrientationPermission = () => {
  if (
    DeviceOrientationEvent &&
    typeof DeviceOrientationEvent.requestPermission === 'function'
  ) {
    // iOS 13+ の Safari
    // 許可を取得
    DeviceOrientationEvent.requestPermission()
    .then(permissionState => {
      if (permissionState === 'granted') {
        // 許可を得られた場合、deviceorientationをイベントリスナーに追加
        window.addEventListener('deviceorientation', e => {
          // deviceorientationのイベント処理
        }
      } else {
        // 許可を得られなかった場合の処理
      }
    })
    .catch(console.error) // https通信でない場合などで許可を取得できなかった場合
  } else {
    // 上記以外のブラウザ
  }
}

// ボタンクリックでrequestDeviceOrientationPermission実行
const startButton = document.getElementById("start-button")
startButton.addEventListener('click', requestDeviceOrientationPermission, false)

参考

How to Request Device Motion and Orientation Permission in iOS 13