ionic-team / capacitor-plugins

Official plugins for Capacitor ⚡️
518 stars 583 forks source link

Capacitor Motion docs: requestPermission only works on Safari #1480

Open kalnode opened 1 year ago

kalnode commented 1 year ago

Bug Report

1. The doc page for Capacitor Motion provides a recommended snippet, however it doesn't work on Chrome (or other non-Safari browsers) because technically only Safari iOS supports requestPermission. The logic needs to be different, see below for a different approach.

2. Secondly, these lines gave me trouble; I presume because I don't use Typescript? It's not mentioned in the doc page one way or another. I understand TS popularity, but... is it good to assume everyone knows it? I've just excluded the lines completely.

import { PluginListenerHandle } from '@capacitor/core';
let accelHandler: PluginListenerHandle;

In any case, this plugin is working better than my old custom sensor code. The advantage the plugin delivers is agnostic standard values (am I right?). Previously I had run different math based on output I was getting (depending on browser).

Working implementation: I see other threads where people have trouble with sensors. Below is my working implementation of Capacitor Motion (web output works; haven't tested native mobile builds yet). Works on Safari (iPhone), Chrome (Android, Ubuntu), Firefox (Android, Ubuntu).

(Vue component)

import { Motion } from '@capacitor/motion'

export default {
    data() {
        return {
            myOrientationHandler: null,
            myAccelerationHandler: null,
        }
    },

    mounted() {
        this.setupMotionListeners()
    }

    methods: {
        async setupMotionListeners() {

            // Check existence of requestPermission; if so, use it
            if (typeof DeviceOrientationEvent.requestPermission === 'function') {

                 // Technically there's DeviceOrientationEvent and DeviceMotionEvent, however I believe it would always be one permission controlling both?

                // This opens a permission prompt to the user
                await DeviceOrientationEvent.requestPermission()
                .catch( (error) => {
                    console.log("Error requestPermission: ", error)
                    return // Exit logic if user denies permission or other error
                })
            }

            // SET LISTENERS
            // Safari iOS (or any other browser that uses requestPermission): At this point, permission is approved
            // Other browsers: Presumably they'll automatically prompt the user for permission if required (?)

            // ORIENTATION
            this.myOrientationHandler = await Motion.addListener('orientation', event => {
                console.log('Device orientation event: ', event)
                // Syncs a 3d object to the device tilt
                if (!this.myCube.spinning) {
                    const x = event.beta / 180 ?? 0
                    const y = event.gamma / 90 ?? 0
                    this.my3dCube.orientation = [x, y]
                }
            })

            // SHAKE
            this.myAccelerationHandler = await Motion.addListener('accel', event => {
                console.log('Device acceleration event: ', event)
                // Spins a 3d object when user shakes their device
                // These are velocity readings, so we just observe if velocity on any axis ever goes above a threshold (e.g. 256)
                if ((event.rotationRate.alpha > 256 || event.rotationRate.beta > 256 || event.rotationRate.gamma > 256)) {
                    this.spinTheCube()
                }
            })
        }

    }
}

Plugin(s)

Capacitor Motion 4.0.2

Capacitor Version

Latest Dependencies:

@capacitor/cli: 4.7.0 @capacitor/core: 4.7.0 @capacitor/android: 4.7.0 @capacitor/ios: 4.7.0

Installed Dependencies:

@capacitor/cli: 4.7.0 @capacitor/core: 4.7.0 @capacitor/android: 4.7.0 @capacitor/ios: 4.7.0

dtarnawsky commented 1 year ago

Should be resolved with this PR if accepted: https://github.com/ionic-team/capacitor-plugins/pull/1614.

It may be nice if the Plugin abstracts a RequestPermissions method so that you don't need to do this.