bug: Motion API is not working in iOS13
Bug Report
Capacitor Version
npx cap doctor output:
💊 Capacitor Doctor 💊
Latest Dependencies:
@capacitor/cli: 1.2.1
@capacitor/core: 1.2.1
@capacitor/android: 1.2.1
@capacitor/ios: 1.2.1
Installed Dependencies:
@capacitor/android 1.2.1
@capacitor/ios 1.2.1
@capacitor/core 1.2.1
@capacitor/cli 1.2.1
[success] Android looking great! 👌
Found 1 Capacitor plugin for ios:
cordova-plugin-ble-central (1.2.2)
[success] iOS looking great! 👌
Affected Platform(s)
- [ ] Android
- [x] iOS
- [ ] Electron
- [ ] Web
Current Behavior
No output from the eventlisteners shown in the example, no error message whatsoever
Expected Behavior
output from the eventlisteners
Sample Code or Sample Application Repo
https://github.com/kxc0re/testmotion
Reproduction Steps
- deploy to iOS device
Other Technical Details
iOS version 13.1.2
yarn --version output: 1.12.3
node --version output: v11.6.0
pod --version output (iOS issues only): 1.8.3
Just wanted to say, that i share the same experience.
Motion plugin just uses the web implementation.
On iOS 13 Apple requires to prompt the user for permission.
You can call DeviceOrientationEvent.requestPermission(); (has to be from an user gesture like button click, otherwise the prompt won't appear)
Motion plugin just uses the web implementation. On iOS 13 Apple requires to prompt the user for permission. You can call
DeviceOrientationEvent.requestPermission();(has to be from an user gesture like button click, otherwise the prompt won't appear)
I can confirm i was able to access the motion api again with integrating the DeviceOrientationEvent.requestPermission();. I use plain js in my Angular/Ionic App like that:
if (typeof (DeviceOrientationEvent as any).requestPermission === 'function') {
(DeviceOrientationEvent as any).requestPermission().then(permissionState => {
if (permissionState === 'granted') {
// do something
}
}).catch(console.error);
}
The problem i have is that i want to check this when my app is getting launched. From these sources https://www.w3.org/TR/orientation-event/#permission https://html.spec.whatwg.org/multipage/interaction.html#triggered-by-user-activation i know that i can only request the permissions with an user interaction. So i thought i create a hidden button which i trigger with an dom element click call after my component was loaded. But so far no success.
@SimonScholl - could you not just prompt the user with a quick explanation alert / dialog and then the tap event on "OK" would trigger the permission prompt? Lots of other apps do this with push notification prompts.
@SimonScholl - could you not just prompt the user with a quick explanation alert / dialog and then the tap event on "OK" would trigger the permission prompt? Lots of other apps do this with push notification prompts.
Would be one solution, after some time i decided to stick to the specification. The problem i see is the behavior on lower iOS versions. Especially iOS 12 blocked the usage of the deviceorientation web api, the problem is safari would still tell you that it has the browser support, so how to proof if the sensor is available?
My plan was to gather some event callbacks in the background to see if data arrives. If not something is wrong, but on iOS 13 i would have to ask for the permissions before doing that.
Motion plugin just uses the web implementation. On iOS 13 Apple requires to prompt the user for permission. You can call
DeviceOrientationEvent.requestPermission();(has to be from an user gesture like button click, otherwise the prompt won't appear)
What happens on iOS 12 then? Will the plugin not work at all? Because they blocked DeviceOrientationAPI access out of security reasons in safari. Is this a factor for the ionic native webview as well?
You only have to request the permission iOS 13, on iOS 12 it will still work without any changes.
In your own code, the if (typeof (DeviceOrientationEvent as any).requestPermission === 'function') will only be true on iOS 13, on Android and iOS 11-12 will be false, in those cases don't show the button for the permission prompting.
I had the same problem, and it even broke for me on iOS 12. I had it working on both versions, but it is still full of HUGE issues. If a user accidentally clicked 'Deny', their phone never prompted them again and even resetting the entire phone's permissions didn't bring back the ability to use the motion data.
Instead of waiting for Apple to figure this out, I started writing a replacement plugin (gist) in swift to access the device's motion data through native APIs and convert them to the Web API equivalent (alpha, beta, gamma, and acceleration w/ gravity).
https://gist.github.com/thomhines/a31f8a33b7bc28dfc55381be3b91dd60
NOTE: I wasn't able to figure out how to get the math right for the 'beta' value, but I didn't need that for my app, so I just left it. Maybe the other values are wrong, too. If someone wants to fork the code to fix the calculations and convert it to a legit Capacitor plugin, they have my blessing and respect!
it wont work with live reload either
since you have to get permission on user input so you do something like this:
window.document.onclick = function () { if ( typeof (DeviceMotionEvent as any).requestPermission() .requestPermission === "function" ) { (DeviceMotionEvent as any) .requestPermission() .then((permissionState) => { if (permissionState === "granted") { //do something } }) .catch(console.error); } else { // handle regular non iOS 13+ devices //do something } };
I've created a new issue for using native code in motion plugin, so I'm going to close this one in favor of the other one since the only way of not needing to request the permission would be to use native code https://github.com/ionic-team/capacitor-plugins/issues/1192
Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of the plugin, please create a new issue and ensure the template is fully filled out.