cordova-plugin-shake
cordova-plugin-shake copied to clipboard
cordova-plugin-shake working on Android, but not iOS
1. What is the context?
I have built an Ionic 5/Capacitor/React app where I have added the cordova-plugin-shake through capacitor by following the Ionic Docs.
2. What does the code look like?
import React from "react";
import { Subscription } from "rxjs";
import { Shake } from "@ionic-native/shake";
// other stuff...
class MagicEightBall extends React.Component {
shakeSubscription: Subscription = new Subscription();
ionViewWillEnter() {
console.log("Magic8Ball ionViewWillEnter()");
this.shakeSubscription = Shake.startWatch().subscribe(() => this.onShake());
}
onShake() {
// process shake
}
}
3. What is the problem?
This works perfectly on Android, but it does not work on iOS. I have made sure the Cordova dependencies have been installed through pod install and that seems to have gone fine. Have been looking for an answer for quite some time now, but I cannot seem to fix it. It has been tested on an iPhone 6S with the latest iOS version as well as on an iPad. The Android version has been run on a Xiaomi Mi 9 and it has worked since the start. Just cannot get it running on iOS.
Any ideas?
I am afraid, the plugin doesn't run out-of-the-box with Capacitor. For getting notified about a shake gesture, on iOS the main controller must register for the motionEnded event. Since Cordova generates the whole main controller by itself, I wrote a hook which patches the generated controller file (see https://github.com/leecrossley/cordova-plugin-shake/blob/master/src/ios/hooks/patchMainViewController.js).
Since you are in Capacitor, you have full control over the iOS code. Therefore it should be easy to add the few lines by yourself.
@Ritzlgrmft Thank you for your response! I don't see a MainViewController.m in the compiled version after running ionic capacitor copy ios
. There is, however, a CDVViewController.m. I will try it there now and see if it will run. Will keep you updated.
@Ritzlgrmft This is what I have in the CDVViewController.m:
@interface CDVViewController () {
}
@property (nonatomic, readwrite, strong) NSMutableDictionary* pluginObjects;
@end
@implementation CDVViewController
// added by cordova-plugin-shake
- (void) motionEnded:(UIEventSubtype)motion withEvent:(UIEvent*)event {
if (event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"CDVShakeDeviceShaken" object:self];
}
}
@end
Unfortunately the shaking is still not being registered. From the start XCode has shown CDVShake::startwatch
by the way, so I know that subscribing to the event is being picked up.
@NintendoEngineer Did you find a fix for this?
I found a solution by myself. Here's how: https://blog.pikodat.com/2020/07/31/capacitor-and-the-ionic-native-shake-plugin/. Hope it helps.
@VeitWeber thanks for this but in your article it's not clear where the file is located. I made it working by modifying this:
But it's inside the Capacitor code... which is not versioned (and probably overwritten sometimes). So it needs to have this inside the pipe, or use npx patch-package
to make sure it's always present.
Can you or the others specify what you chose to go with? (maybe I'm modifying the wrong thing...)
Thank you,
You can create a new swift file in your app and override CAPBridgeViewController: