amazon-web-servicesreact-nativeexpoamazon-sns

Using SNS to send push notifications - Expo App


I am creating an Expo app that will use push notifications. I do not want to use Expo's server for that and instead I want to use AWS SNS. This is what I have done:

  1. Created the app in Firebase and obtained the API Key.
  2. Created the platform application on SNS using the API key obtained in step 1.
  3. Used expo to obtained the device token.
  4. Created an endpoint on SNS in the application created in step 2.

When I try to send a push notification, it doesn't work. I tried:

I am thinking that if I am able to build the app and obtain the device token I may be able to make it work, but no luck. Any idea on what I am doing wrong or what I am supposed to be doing?


Solution

  • After 2 days of fighting to get this to work I finally did it. I am going to provide all the steps I followed in hopes that this can help other people:

    1. Create a Firebase Project.
      • Click on "Add Project"
      • Provide a name. Click on "Continue"
      • Click on "Create Project"
      • Once the project is ready, click on "Continue"
    2. Click on the gear icon right next to where it says "Project Overview"
    3. Click on Project Settings.
    4. In the page that shows up click on Cloud Messaging
    5. Copy the value for "Server key". You will use it later when creating an application platform in SNS.
    6. In that same "settings" page click on the "General" tab.
    7. At the bottom of the page you are going to see a section that says "Your Apps". It should say: "There are no apps in your project". Click on the icon for Android.
    8. This is an important step. You need to provide the "Android package name". Go to your Expo app and find the value for android.package. Copy it and put it where it asks for the Android package name on Firebase.
    9. Click on "Register App".
    10. Important step. Click on the button that says "Download google-services.json".
    11. Save the file AT THE ROOT OF YOUR EXPO PROJECT.
    12. Go back to your app.json file in your Expo project. Where it has the android value make sure this is what you have at least:
    "android": {
          "googleServicesFile": "./google-services.json",
          "package": "com.astest.mypackage",
          "useNextNotificationsApi": true
     },
    
    1. Follow the instructions here on how to set up your client app. Make sure you do not include the sendPushNotification() function since you will actually be using SNS instead.

    2. In the registerForPushNotificationsAsync() function make sure you use .getDevicePushTokenAsync() instead of .getExpoPushTokenAsync()

    3. Create a platform application in SNS

    1. In your code, make sure you create an application endpoint in SNS. Or do it through the console.

    2. Test the set up by sending a test message using the console in SNS. Select your endpoint and then click on "Publish message".

    3. Click on "custom payload for each delivery".

    4. use this code:

    {
      "GCM": "{ \"notification\": {\"title\": \"Title of notification\", \"body\": \"It works\" } }"
    }
    
    1. Click on publish message.

    2. To publish a message programmatically you can do:

    var sns = new AWS.SNS({ apiVersion: '2010-03-31', region: 'us-east-1'})
        
            let notification = JSON.stringify({
                'notification': {
                    'title': "title of notification",
                    'body': "Your message goes here",
                    'data': {}
                }
            });
        
        
            var params = {
                Message: JSON.stringify({
                    GCM: notification
                }),
                MessageStructure: "json",
                TargetArn: "###Your Target ARN##"
            };
        
            sns.publish(params, function(err, data) {
                if (err) {
                    console.log("There was an error sending the push notification----> ", err)
                } // an error occurred
                else{
                    console.log("Push notification sent successfully!!!! ", data);
                }                // successful response
            });
    

    Now, this is only for Android of course. But it works! Adapting it to APN shouldn't be too difficult.

    EDIT 1 If you want your Expo, managed flow, app to respond to the notification you are sending you need to make a couple of changes. I spent the last 3 days trying to figure this out and I finally did.

    According to the Expo documentation there are 2 types of push notifications you can send, "notification" and "data". In the example I provided in the steps above I was using "notification". The problem with that is that Expo "is not made aware that the notification is being received" when you use notifications, which means you can't respond to notifications. Therefore, if you need to respond or parse the response received in the notification you need to use a push notification of type "data".

    Therefore, in the code example I gave above you need to change the word "notification" for "data".

    In addition to sending "data" push notification instead of just "notifications", you must include the "experienceId in your payload, which you can get from your app

    Defaults to Constants.manifest.id exposed by expo-constants. In the bare workflow, you must provide a value which takes the shape @username/projectSlug, where username is the Expo account that the project is associated with, and projectSlug is your slug from app.json.

    The other change you need to make is the part where the content of your push notification goes. In the code I gave above I included it in a property called "body". With the "data" type of notification it needs to be changed to "message"

    Also, the part where you add your key-value pairs also need to change. In the example I gave above the propertyis called "data", but this time we need to change it to "body"

    An this is the resulting code:

    let dataNotification = JSON.stringify({
                'data': {
                    'title': title,
                    'message': message,
                    'body': { your key-value-pairs}, 
                    'experienceId': "@yourExpoUsername/Your-Project-Slug"
                }
            });