expo: [IOS][PRODUCTION] getAsync is granted, getExpoPushTokenAsync throws error

Environment

Expo CLI 2.3.3 environment info:
    System:
      OS: macOS High Sierra 10.13.6
      Shell: 5.3 - /bin/zsh
    Binaries:
      Node: 8.6.0 - ~/.nvm/versions/node/v8.6.0/bin/node
      Yarn: 1.7.0 - /usr/local/bin/yarn
      npm: 5.3.0 - ~/.nvm/versions/node/v8.6.0/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
    IDEs:
      Android Studio: 3.1 AI-173.4670197
      Xcode: 10.1/10B61 - /usr/bin/xcodebuild
    npmPackages:
      expo: ^30.0.0 => 30.0.2
      react: 16.3.1 => 16.3.1
      react-native: https://github.com/expo/react-native/archive/sdk-30.0.0.tar.gz => 0.55.4
      react-navigation: ^2.5.5 => 2.5.5
    npmGlobalPackages:
      expo-cli: 2.3.3

  Diagnostics report:
    https://exp-xde-diagnostics.s3.amazonaws.com/muzk-857feb81-9501-493f-befd-fbc6361bbe21.tar.gz

Target: iOS Standalone

Steps to Reproduce

  1. Install the standalone iOS application.
  2. Open the app and accept push notification permission. After this, you can get expo token as expected.
  3. Now, uninstall the application.
  4. Install it again.
  5. It won’t ask you for permissions.
  6. Now Permissions.getAsync(Permissions.NOTIFICATIONS) will return granted 😄 while Notifications.getExpoPushTokenAsync() throws an exception.

Here is my code:

  const { status: existingStatus } = await Permissions.getAsync(Permissions.NOTIFICATIONS);
  let finalStatus = existingStatus;

  // only ask if permissions have not already been determined, because
  // iOS won't necessarily prompt the user a second time.
  if (existingStatus !== 'granted') {
    // Android remote notification permissions are granted during the app
    // install, so this will only ask on iOS
    const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
    finalStatus = status;
  }

  // Stop here if the user did not grant permissions
  if (finalStatus !== 'granted') {
    return false;
  }

  // Get the token that uniquely identifies this device
  const token = await Notifications.getExpoPushTokenAsync();

Expected Behavior

  • In step 6, getExpoPushTokenAsync() should return a valid token and not throw an exception because the permission is granted.

Actual Behavior

  • In step 6, getExpoPushTokenAsync() throws an exception (This app does not have permission to show notifications)

Maybe this issue is related to:

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 5
  • Comments: 18 (3 by maintainers)

Most upvoted comments

Just to clarify — Expo notifications (getting Expo token too) are supposed to not work in ejected apps. 😕

When a native application is built, for it to receive the notifications we have to add certificates to the bundle, which we know if we build the app in Turtle. Moreover, the certificates are required when we want to send the notification (authentication against APNS).

That’s why you can send notifications with Expo servers when the app is Turtle-built (the sender, i. e. Expo server knows what certificate is in the Turtle-built app) and why you cannot use Expo servers to send notifications to ejected apps (you are the one adding the certificate and building the app).

Same problem here, I’m getting granted back from Permissions.getAsync but getting error below when trying to get the token (let token = await Notifications.getExpoPushTokenAsync())

[Unhandled promise rejection: Error: unsupported URL]

  • node_modules/react-native/Libraries/BatchedBridge/NativeModules.js:146:41 in createErrorFromErrorData
  • node_modules/react-native/Libraries/BatchedBridge/NativeModules.js:95:55 in <unknown>
  • … 5 more stack frames from framework internals

I ejected my app too. But I thought Expo still added some fixes to make it work even if the app is ejected. I’m on SDK 32.

I’m still using https://docs.expo.io/versions/v32.0.0/sdk/notifications/#notificationsgetdevicepushtokenasyncconfig to get the device token and https://github.com/node-apn/node-apn to send notification backend. But would love to simply use Expo backend and Frontend.