Setting up Android Push Notifications with AWS Amplify

Daniel Dantas (@dantasfiles)
6 min readJan 14, 2020

--

In this post, we set up a React Native app using AWS Amplify to receive Android Push Notifications. If you are interested in iOS Push Notifications, see Nader Dabit’s official post.

The example code for this post uses React Native 61.5 and AWS Amplify 2.2.2, and is at https://github.com/dantasfiles/AmplifyAndroidPush

This is based on the AWS Amplify Push Notification documentation. I found the process to require a lot of care, so I wrote this up to examine and detail some steps that I had issues with.

This post is part of a series:
- Setting up Android Push Notifications with AWS Amplify
- Testing Push Notifications with AWS Amplify & CLI
- Handling Incoming Push Notifications in AWS Amplify
- Customizing the Appearance of Android Push Notifications with AWS Amplify

Create a new React Native project
> npx react-native init AmplifyAndroidPush

Install the AWS Amplify libraries, explicitly including push notifications
> npm install aws-amplify aws-amplify-react-native amazon-cognito-identity-js @aws-amplify/pushnotification

Initialize AWS Amplify in the project, using the default settings
> amplify init

Google Firebase Setup

Go to the Google Firebase Console

Add a project

Enter the project’s name

Enable Google Analytics if you want to be able to see stats

Choose or create a Google Analytics account for the project

Continue to the Project Overview page

Add Firebase to your Android app

Enter the Android package name

Recall that your Android package name can be found in android/app/build.gradle

// android/app/build.gradle
android {
defaultConfig {
applicationId "com.amplifyandroidpush"
}
}

As instructed by Firebase console, download google-services.json and place it in the android/app directory

As instructed by Firebase console, add the latest version of com.google.gms:google-services to android/build.gradle

// android/build.gradle
buildscript {
dependencies {
classpath 'com.google.gms:google-services:4.3.3'
}
}

As instructed by Firebase console, add the latest versions of com.google.firebase:firebase-messaging and com.google.firebase:firebase-analytics to android/app/build.gradle

// android/app/build.gradle
dependencies {
implementation 'com.google.firebase:firebase-messaging:20.1.0'
implementation 'com.google.firebase:firebase-analytics:17.2.1'

}
apply plugin: 'com.google.gms.google-services'

Note: The AWS Amplify Push Notification documentation shows the line compile project(’:@aws-amplify/pushnotification’) I believe that’s inserted by manually linking @aws-amplify/pushnotification and won’t show up if you are using React Native post-0.60 auto-linking. Do not manually insert the compile line into the build.gradle file to match the documentation — if you do, you will get the following error:

* What went wrong:
A problem occurred evaluating project ':app'.
> Project with path ':@aws-amplify/pushnotification' could not be found in project ':app'.

Continue to return to the Project Overview page, then click the Gear icon, then Project Settings

In the Settings: Cloud Messaging tab, save the Project credentials: Server key. You will need this when you run amplify add notifications later.

As instructed in the AWS Amplify Push Notification documentation, add the <!-- [START Push notification config --> lines to android/app/src/main/AndroidManifest.xml
Since this step is exactly like the documentation, I won't replicate the lines here.

Setup AWS Amplify

Add authentication, using the default settings
> amplify add auth

Note: If you don’t add authentication manually here, the next step (amplify add notifications) would add authentication implicitly, but it would only create an identity pool, not both a user pool and an identity pool like this step does.

Add push notifications, choose the FCM (Firebase Cloud Messaging) push notification channel, and, when prompted for an ApiKey, enter the Project credentials: Server key that you previously saved from the Google Firebase Console.

> amplify add notifications
? Choose the push notification channel to enable. FCM
An Amazon Pinpoint project will be created for notifications.
? Provide your pinpoint resource name: AmplifyAndroidPushXXXXX
√ Successfully created Pinpoint project: AmplifyAndroidPushXXXXX-env
√ Successfully set the IAM policy
Adding notifications would also add the Auth category to the project if not already added.
Successfully updated auth resource locally.
Execute "amplify push" to update the Auth resources in the cloud.
? ApiKey XXXXXXX
√ The FCM channel has been successfully enabled.

Note: Do NOT also run amplify add analytics because amplify add notifications already initializes an AWS Pinpoint project, called AmplifyAndroidPushXXXXX-env

Push your authentication setup into AWS (your analytics setup was already pushed during the amplify add notifications step).
> amplify push

Configure AWS Amplify in index.js

// index.js
import Amplify from 'aws-amplify';
import config from './aws-exports';
Amplify.configure(config);

Note: you do not have to separately run PushNotification.configure

Configure push notification handler functions in App.js

// App.js
import PushNotification from '@aws-amplify/pushnotification';
PushNotification.onRegister
(token => {
console.log('onRegister', token);
});
PushNotification.onNotification(notification => {
if (notification.foreground) {
console.log('onNotification foreground', notification);
} else {
console.log('onNotification background or closed',
notification);
}
// extract the data passed in the push notification
const data = JSON.parse(notification.data['pinpoint.jsonBody']);
console.log('onNotification data', data);
// iOS only
notification.finish(PushNotificationIOS.FetchResult.NoData);
});
PushNotification.onNotificationOpened(notification => {
console.log('onNotificationOpened', notification);
// extract the data passed in the push notification
const data = JSON.parse(notification['pinpoint.jsonBody']);
console.log('onNotificationOpened data', data);
});

Note: Place these components only at the top-level, not inside a React component. If you do place them inside a React component, like in an Effect hook, your onNotification and onNotificationOpened handler functions will not be triggered if the app is closed (not running in foreground or background) when a push notification is received and clicked on.

PushNotification.onRegister

Your PushNotification.onRegister handler function is supposed to be called by AWS Amplify the first time the FCM device token is fetched and cached. All future launches of the app should not trigger this handler function, as the FCM device token is already cached and does not need to be re-fetched.

Note: In my testing, I never noticed my PushNotification.onRegister handler function being called, even though the FCM device token was correctly fetched and cached by AWS Amplify. I didn’t find this configuration function that useful in practice (as opposed to PushNotification.onNotification and PushNotification.onNotificationOpened), so it didn’t matter much.

Additional Note: I’ve seen Github comments that say that you have to write the following function to manually update the Pinpoint endpoint with the device token once it’s received:

PushNotification.onRegister(token => {
PushNotification.updateEndpoint(token);
});

I didn’t find this to be true. AWS Amplify will call PushNotification.updateEndpoint automatically in initializeAndroid and initializeIOS to update AWS Pinpoint with the FCM device token. No manual calls to PushNotification.updateEndpoint should be necessary.

For information on the PushNotification.onNotification and PushNotification.onNotificationOpened configuration functions, see Handling Incoming Push Notifications in AWS Amplify.

Your initial setup is now complete.

To test your configuration, see Testing Push Notifications with AWS Amplify & CLI.

--

--

Daniel Dantas (@dantasfiles)

I create guides to help me fully understand the issues that I’m encountering and fixing. Web: dantasfiles.com Email: daniel@dantasfiles.com