React-Native Push Notifications with Amazon SNS

Here’s a simple guide on how to register a mobile device and how to create an Amazon SNS endpoint programmatically.

Amazon SNS interacts with APN/FCM (and other services) for you, which scales easier than building your own implementations.

A simple diagram of how it works:

straight from the aws blog

For security I’ll show you how to do this using an Amazon Cognito Identity Pool (which you need to setup on your own), but I’ll also give you the less secure alternative that doesn’t require one.

Requirements

  1. Credentials for your AWS or a Cognito identity pool.
  2. ARN for iOS (example: “arn:aws:sns:us-east-1:XXXXXXXXX:app/APNS_SANDBOX/CoolApp“)
  3. ARN for Android (example: “arn:aws:sns:us-east-1:XXXXXXXXX:app/GCM/CoolApp”)
  4. React-Native Notifications installed: https://wix.github.io/react-native-notifications/docs/getting-started/
  5. AWS SDK installed: https://www.npmjs.com/package/aws-sdk#getting-Started
  6. A backend to receive your subscription info (and to trigger the notification with SNS; neither is covered here)

First I’ll give you a breakdown, then you’ll find the whole working code below.

Getting Started

Register the device and get the token

import { Notifications } from 'react-native-notifications';//register the device with the push service
Notifications.registerRemoteNotifications();
//setup the onRegistration listener (lambda for clarity)
Notifications.events().registerRemoteNotificationsRegistered((token) => onRegistration(token);

In your onRegistration, you need to first get your credentials

Setup the AWS Credentials

Using a Cognito Identity Pool

import AWS from 'aws-sdk/dist/aws-sdk-react-native';AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: cognitoPool }, {region:'us-east-1'});
AWS.config.credentials.getPromise();

Or by hard-coding your credentials (which is not recommended)

AWS.config = new AWS.Config();
AWS.config.accessKeyId = "accessKey";
AWS.config.secretAccessKey = "secretKey";
AWS.config.region = "us-east-1";

Then you can go ahead and create the SNS endpoint specific for this device and send it to your backend.

Create the endpoint

const sns = new AWS.SNS();
sns.createPlatformEndpoint({ARN, Token}, callback);

After creating the endpoint, you want to get it’s attributes just to double check it’s ready to go. This flow is suggested by Amazon, even if it seems redundant.

Get the Endpoint Attributes

sns.getEndpointAttributes({EndpointArn}, callback);

After you get the attributes, make sure the endpoint is enabled and make sure that the tokens match. After that you can go ahead and send the created endpoint and the device token to your backend.

All the Codes

import { Notifications } from 'react-native-notifications';
import AWS from 'aws-sdk/dist/aws-sdk-react-native';
import { Platform } from 'react-native';
const cognitoPool = "us-east-1:XXXXX-XXXX-XXXXX-XXXX-XXXX";
const iOSARN = “YOUR-IOS-ARN“;
const androidARN = "YOUR-ANDROID-ARN";
const onRegistration = async(event)=>{ try{ console.log("Device Token Received", event.deviceToken); const endpointParams = {
PlatformApplicationArn: Platform.OS === "android" ?
androidARN : iOSARN,
Token: event.deviceToken
};
//fetch credentials from Cognito to create the SNS endpoint
AWS.config.update({region:'us-east-1'});
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: cognitoPool
},
{region:'us-east-1'});
await AWS.config.credentials.getPromise(); const endpointARN = await createARNAsync(endpointParams); if(!endpointARN){
throw new Error('error creating endpointARN');
}
console.log("endpointARN:", endpointARN); //get endpoint attributes
let attributes = await getAttributesAsync({
EndpointArn: endpointARN });
console.log('attributes:',attributes); //if token does not match current token
//or the endpoint is disabled, throw an error
if(attributes
&& !attributes.Enabled ||
attributes.Token !== event.deviceToken){
throw new Error('endpoint error');
}
//send the data to the backend
//registerDevice(endpointARN, event.deviceToken);
}catch(e){ //create the endpoint again and store it
return 0
}};//register the device with the push service
Notifications.registerRemoteNotifications();
//setup the onRegistration listener
Notifications.events().registerRemoteNotificationsRegistered(onRegistration);

Here’s the async helper functions. Put them wherever you’d like and btw, you don’t have to create separate instances in each function if you don’t want to.

const createARNAsync = (params) => new Promise((resolve,reject) => {  const sns = new AWS.SNS();
sns.createPlatformEndpoint(params,(err, data)=>{
console.log("created endpoint", err, data); if(err || !data.EndpointArn){
return err ?
reject(err) :
reject('arn is missing');
}
resolve(data.EndpointArn); });
});
const getAttributesAsync = (params) => new Promise((resolve,reject) => { const sns = new AWS.SNS();
sns.getEndpointAttributes(params,(err, data)=>{
console.log('got attrs:', err, data); if(err || !data.Attributes){
return err ?
reject(err) :
reject('attributes are missing in the response');
}
resolve(data.Attributes); });
});

Hopefully this helps get your app and device registered for push notifications since the docs don’t offer many examples.

--

--

--

Mobile Dev @ ClaimWizard & Freelancing with LiliaSoftware

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Don’t Use Switch or If-Else in JavaScript, Instead, Try This

Exploring Using SVG Over HTML/DOM for Performance

https://t.me/MetalSwapAirdrop_bot?start=r0620486145

Why did we choose Puppeteer for scraping?

How to build a Tailwind CSS timeline component with Flowbite

Differences between a JavaScript statement and expression

Debugging NodeJS with Chrome Inspector (DevTools)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Jorge Gonzalez Vallejo

Jorge Gonzalez Vallejo

Mobile Dev @ ClaimWizard & Freelancing with LiliaSoftware

More from Medium

How to upload multiple images to AWS S3 in react-native App

React Native App Development: 4 Promising Local Databases That You Must Try

Integrate Stripe Terminal Payments into your React Native application

React Native — Multiple Command Produce — iOS