DEV Community

Wenchen (Neo) Li
Wenchen (Neo) Li

Posted on • Updated on

How to requestPermission for devicemotion and deviceorientation events in iOS 13+

Background

Since iOS 12.2, Apple decided that for privacy reasons, the in-browser access to the device motion and orientation events is off by default. And now maybe they realized this might be a mistake, so in iOS 13 they changed the permission request behavior similar to how the camera permission is requested.

So now when we try to addEventListener to devicemotion or deviceorientation, we would see this warning in the console:

Console warnings: No device motion or orientation events will be fired until permission has been requested and granted.

To request permission, we would just need to call a method on the DeviceMotionEvent or DeviceOrientationEvent: requestPermission 😂 It would return a promise that always resolve to a PermissionState which could be granted or denied (so basically Promise<'granted'|'denied'>).

One more thing

One more thing to keep in mind is that requestPermission could only be called on a user gesture (e.g. click). This is reasonable UX too as we would want to tell users why we are asking for such permissions and let them confirm before prompting them so that they see it coming.

Otherwise you would get this error:

Console error: NotAllowedError: Requesting device orientation or motion access requires a user gesture to prompt

The code to copy

For devicemotion events:

  function onClick() {
    // feature detect
    if (typeof DeviceMotionEvent.requestPermission === 'function') {
      DeviceMotionEvent.requestPermission()
        .then(permissionState => {
          if (permissionState === 'granted') {
            window.addEventListener('devicemotion', () => {});
          }
        })
        .catch(console.error);
    } else {
      // handle regular non iOS 13+ devices
    }
  }
Enter fullscreen mode Exit fullscreen mode

and for deviceorientation events:

  function onClick() {
    // feature detect
    if (typeof DeviceOrientationEvent.requestPermission === 'function') {
      DeviceOrientationEvent.requestPermission()
        .then(permissionState => {
          if (permissionState === 'granted') {
            window.addEventListener('deviceorientation', () => {});
          }
        })
        .catch(console.error);
    } else {
      // handle regular non iOS 13+ devices
    }
  }
Enter fullscreen mode Exit fullscreen mode

That's it. Thank you for reading!

Top comments (5)

Collapse
 
andreasvirkus profile image
ajv

Should also mention that HTTPS is required to access both of these APIs

Collapse
 
amirkhan81 profile image
Amir Khan

Do you know if its possible to check if permission has already been granted without a user event?

Collapse
 
bhav profile image
Bhavesh Kakwani

Fantastic! Thank you so much, this helped with a threejs project I'm working on :)

Collapse
 
victordenisenko profile image
Victor Denisenko

How to remember the permission for DeviceOrientation? I need to ask it ever time after closing the browser and opening it again.

Collapse
 
arielhasidim profile image
Ariel

How can I customise the permission dialog?