question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

iOS Push Notification problems: "APNS token has not been set" on second run. SDK v31

See original GitHub issue

Environment

  Expo CLI 2.6.0 environment info:
    System:
      OS: macOS 10.14
      Shell: 5.5.1 - /usr/local/bin/zsh
    Binaries:
      Node: 8.11.3 - /usr/local/bin/node
      Yarn: 1.10.1 - /usr/local/bin/yarn
      npm: 5.6.0 - /usr/local/bin/npm
      Watchman: 4.9.0 - /usr/local/bin/watchman
    IDEs:
      Xcode: 10.1/10B61 - /usr/bin/xcodebuild
    npmPackages:
      expo: ^31.0.2 => 31.0.6
      react: 16.5.0 => 16.5.0
      react-native: https://github.com/expo/react-native/archive/sdk-31.0.0.tar.gz => 0.57.1
    npmGlobalPackages:
      expo-cli: 2.6.0

iOS 12, ejected ExpoKit app. Tested on iPhone 6S, 6 Plus, 7 Plus and XR.

Steps to Reproduce

I apologize that this is a bit tedious to reproduce, mostly because you need to setup all the necessary push notification certificates and provisioning profiles with Apple for your associated bundle id. Here’s a guide. Once that is done, these are the necessary steps to reproduce it.

  1. initialize a new project with expo init, then run expo eject and choose the expokit option. Enter your bundle id that you used when configuring push notifications with Apple.

  2. Run the usual pod update && pod install.

  3. Replace app.js with the following:

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

import { Permissions, Notifications } from 'expo';

async function registerForPushNotificationsAsync() {
	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;
	}

	// Get the token that uniquely identifies this device
	let token = await Notifications.getDevicePushTokenAsync();
	return token;
}

export default class App extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			token: { status: 'no token' },
		};
	}

	componentDidMount() {
		this.getToken();
	}

	async getToken() {
		const token = await registerForPushNotificationsAsync();
		this.setState({ token });
	}

	render() {
		return (
			<View style={styles.container}>
				<Text>Token: {JSON.stringify(this.state.token)}</Text>
			</View>
		);
	}
}

const styles = StyleSheet.create({
	container: {
		flex: 1,
		backgroundColor: '#fff',
		alignItems: 'center',
		justifyContent: 'center',
	},
});
  1. Open the xcode workspace, enable push notifications under entitlements, uncheck Debug executable in product > scheme and run the project on an iOS device.

  2. Give push notification permissions when asked, and verify that your token is printed on the screen.

  3. Close the app (don’t just background it, you need to actually close it).

  4. Reopen the app, and notice the warning: APNS token has not been set, even though status is granted. Notifications are not received within the app at this point. They still work if the app is backgrounded or closed.

Expected Behavior

Token is returned from registerForPushNotificationsAsync on subsequent runs.

Actual Behavior

Unhandled Promise Rejection: Error: APNS token has not been set. No token is returned.

Reproducible Demo

See reproduction steps.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:13 (5 by maintainers)

github_iconTop GitHub Comments

6reactions
jacobsmithcommented, Mar 2, 2019

For anyone else who stumbles here from google, I was able to get the actual APNS token by adding [application registerForRemoteNotifications] to my AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [application registerForRemoteNotifications];
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

(Of note, I do not have the code that PushNotificationIOS tells you to add to the AppDelegate.m - I was having conflicts with ExpoKit and AppDelegate.m both trying to declare handlers for notifications.

then in my JS code, I can call:

    Notifications.getDevicePushTokenAsync().then(success => this.setState({ text: `Expo: ${JSON.stringify(success)}`}))

that returns { "type": "apns", "data": "<32 byte apns token>" }

I’m then able to handle notifications with:

Notifications.addListener(this._handleNotification)

And, additionally, the notification sent to APNS has to be of a certain form because ExpoKit does some validation of the notification. I believe this is a private API, so things may change in the future, but it is necessary for now:

{
  "experienceId": <expo bundle identifier - eg, @username/project>,
  "body": {
    <whatever data you want to pass, params for your client app, etc.>
  }
}

I’m using the RPush gem and the alert key of the notification object is the actual text displayed - I’m not sure what that corresponds to in “pure” APNS, but hopefully this helps someone along the way.

Sorry if this is a bit garbled, it’s the result of about 20 hours fighting with APNS and ExpoKit in a detached Expo app (:

1reaction
tsapetacommented, Jun 30, 2020

Looks like the workaround has been found, so I’m closing this issue as ExpoKit is also no longer supported. Recently we’ve rewritten Notifications API from scratch so you can give them a try if you’re still hitting this.

Read more comments on GitHub >

github_iconTop Results From Across the Web

push notification problem | Apple Developer Forums
The error is "Notification error: APN invalid token" when i install the app from App Store, but works fine when I install from...
Read more >
Bountysource
iOS Push Notification problems : "APNS token has not been set" on second run. SDK v31.
Read more >
ios - What are the possible reasons to get APNs responses ...
Let's pretend that the BadDeviceToken error is due to the second case--that the device token registered by the app does not match the...
Read more >
Mobile App Messaging SDK for iOS — Regular Releases
The SDK was storing the push token being passed in method isRegisteredForPushNotifications that was further used to register for push notifications on calling ......
Read more >
Release Notes - CEE
Fixed issue where nudge set to trigger on nudge action of modal bottom sheet was not showing. Android Smartech SDK 3.1.41. Released 9th,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found