Skip to content

v2.0.1

Compare
Choose a tag to compare
@ide ide released this 04 Feb 08:27

v2.0.1 of the Exponent SDK has several breaking changes, better error handling, networking-level performance improvements, and new features for push notifications.

Breaking changes

Instead of exporting several functions, the package has one default export, which is the Exponent API client class.

  • isExponentPushToken is now a static method: Exponent.isExponentPushToken(token)
  • Instantiate an Exponent client object to make calls to the Exponent server: new Exponent()
  • Use the Exponent instance to send a push notification: exponent.sendPushNotificationsAsync(messages)

sendPushNotificationsAsync accepts an array of up to 100 messages. This is what an example message looks like:

{
  // The push token for the app user to whom you want to send the notification
  to: 'ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]',
  sound: 'default',
  message: 'This is a test notification',
  data: {withSome: 'data'},
}

Note that the exponentPushToken field is now called to! See the end of these release notes for the full message object specification.

Error handling

The sendPushNotificationsAsync async function throws an error when the entire request fails either due to networking problems or server-side errors. But when some push notifications are successfully sent and others fail (and also if all are successful), you get back an array of push receipts. Each push receipt is a small JSON object that looks like: {"status": "ok"} on success and {"status": "error"} on error. Push receipts for errors also contain more information and often look like this:

{
  "data": [{
    "status": "error",
    "message": "\"ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]\" is not a registered push notification recipient",
    "details": {
      "error": "DeviceNotRegistered"
    }
  }]
}

Important: in particular, look for an details object with an error field. If present, it may be one of these values: DeviceNotRegistered, MessageTooBig, MessageRateExceeded, or InvalidCredentials. You should handle these errors like so:

  • DeviceNotRegistered: the device cannot receive push notifications anymore and you should stop sending messages to the given Exponent push token.
  • MessageTooBig: the total notification payload was too large. On Android and iOS the total payload must be at most 4096 bytes.
  • MessageRateExceeded: you are sending messages too frequently to the given device. Implement exponential backoff and slowly retry sending messages.
  • InvalidCredentials: your iOS push certificate for your standalone app is invalid (ex: you may have revoked it)

If we couldn't deliver the message to the Android or iOS push notification service, the receipt's details may also include service-specific information. This is useful mostly for debugging and reporting possible bugs to us.

Performance improvements

The new Exponent Node SDK connects to our new server API which has lots of server-side improvements like faster response times and pooled connections to the Android and iOS push notification services. It also supports a batch API.

Instead of sending just one notification, the SDK supports sending an array of push notifications. This way when you want to send a notification to many users, you can send up to 100 per request (to send more than 100, divide your notifications into chunks).

New push notification features

We now support many more options for sending push notifications, like setting the badge count on iOS, playing a sound, setting a TTL or expiration date (if your notification is not urgent, setting these fields tells Apple or Google to hang on to your notification if they can't deliver it right away), and the priority of your notification. See these fields:

type PushMessage = {
  /**
   * An Exponent push token specifying the recipient of this message.
   */
  to: string,

  /**
   * A JSON object delivered to your app. It may be up to about 4KiB; the total
   * notification payload sent to Apple and Google must be at most 4KiB or else
   * you will get a "Message Too Big" error.
   */
  data?: Object,

  /**
   * The title to display in the notification. On iOS this is displayed only
   * on Apple Watch.
   */
  title?: string,

  /**
   * The message to display in the notification
   */
  body?: string,

  /**
   * A sound to play when the recipient receives this notification. Specify
   * "default" to play the device's default notification sound, or omit this
   * field to play no sound.
   */
  sound?: 'default' | null,

  /**
   * Time to Live: the number of seconds for which the message may be kept
   * around for redelivery if it hasn't been delivered yet. Defaults to 0.
   *
   * On Android, we make a best effort to deliver messages with zero TTL
   * immediately and do not throttle them
   *
   * This field takes precedence over `expiration` when both are specified.
   */
  ttl?: number,

  /**
   * A timestamp since the UNIX epoch specifying when the message expires. This
   * has the same effect as the `ttl` field and is just an absolute timestamp
   * instead of a relative time.
   */
  expiration?: number,

  /**
   * The delivery priority of the message. Specify "default" or omit this field
   * to use the default priority on each platform, which is "normal" on Android
   * and "high" on iOS.
   *
   * On Android, normal-priority messages won't open network connections on
   * sleeping devices and their delivery may be delayed to conserve the battery.
   * High-priority messages are delivered immediately if possible and may wake
   * sleeping devices to open network connections, consuming energy.
   *
   * On iOS, normal-priority messages are sent at a time that takes into account
   * power considerations for the device, and may be grouped and delivered in
   * bursts. They are throttled and may not be delivered by Apple. High-priority
   * messages are sent immediately. Normal priority corresponds to APNs priority
   * level 5 and high priority to 10.
   */
  priority?: 'default' | 'normal' | 'high',

  // iOS-specific fields

  /**
   * Number to display in the badge on the app icon. Specify zero to clear the
   * badge.
   */
  badge?: number,
}