LocalNotifications in iOS with ExpoKit detached


#1

Hello,

I have been trying to get Local notifications to come through to my Javascript code using a detached ExpoKit based on 20.0.0.

The local notifications activate my native code generated by exp detach:

- (void)application:(UIApplication *)application didReceiveLocalNotification:(nonnull UILocalNotification *)notification
{
    [[ExpoKit sharedInstance] application:application didReceiveLocalNotification:notification];
}

If I place a breakpoint here in Xcode, all is well.

However the code I have added in App.js to handle it never is executed:

  async componentWillMount() {
    this._loadAssetsAsync();
    let result = await Permissions.askAsync(Permissions.NOTIFICATIONS);

    if (Constants.isDevice && result.status === "granted") {
      console.log("Notification permissions granted.");
    }

    Notifications.addListener(this._handleNotification);
  }

  _handleNotification = ({ origin, data }) => {
    console.info(
      `Notification (${origin}) with data: ${JSON.stringify(data)}`
    );
  };

Notably, when I step through it in the Chrome debugger, it completely skips the call to Permissions.
There is no logging of granted permissions or any other error output.
It does register the listener, but the listener is never called.

When I schedule an immediate breakpoint it does invoke the native code and trigger the native breakpoint, but again never triggers the javascript handler.

Should this be working with ExpoKit?


#2

Hmm, this might be an issue with the ExpoKit template project we generate. Remote notifications don’t work in ExpoKit, so we omit some of the permissions callbacks from your AppDelegate, but actually some of them might be needed for local notifications.

Try adding this in your AppDelegate and breakpointing in it:

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(nonnull UIUserNotificationSettings *)notificationSettings
{
 ...
}

The step issue in the Chrome debugger might be because it’s an await. Not sure if breakpoints are reliable near those calls.


#3

Thank you, when I do that the method is invoked twice, so that’s good.

However on the JS side my handler is still not invoked. I do receive a message in the console

Scheduling immediate notification: {localNotification: {…}}
console.js:26 Immediate notification scheduled (E8F2505D-0D95-4BFE-9B95-C8C7B1B0B2F9)
console.js:26 Push notification received with data: {"type":"immediate"}

Note that I am testing this with an immediate notification generated with

  _sendImmediateNotification() {
    const localNotification = {
      title: "Immediate testing Title",
      body: "Testing body",
      data: { type: "immediate" }
    };

    console.log("Scheduling immediate notification:", { localNotification });

    Notifications.presentLocalNotificationAsync(localNotification)
      .then(id => console.info(`Immediate notification scheduled (${id})`))
      .catch(err => console.error(err));
  }

When I trigger it from a local push registered from my native code, I don’t get any messages at all about a push notification being received, and my handler does not get invoked.

This is true even if the app is backgrounded. I have confirmed the local notification is invoking the native handler in all 3 cases.

- (void)application:(UIApplication *)application didReceiveLocalNotification:(nonnull UILocalNotification *)notification
{
    [[ExpoKit sharedInstance] application:application didReceiveLocalNotification:notification];
}