AWS Lambda running Python and Pusher Beams for Android push notifications

Introduction

Introduction

Pusher Beams allows you to customize push notifications you send to your devices via a server. However it can be expensive to run a server 24 hours a day 7 days a week and we may only need to send notifications every so often. This is where AWS Lambda can help. Lambda functions are serverless and work on a pay as you go model (with a generous free tier). This means that you only pay for when you use the function. We’re going to explore how we can setup Pusher Beams on an Android client using an AWS Lambda function running Python to trigger the notifications.

Prerequisites

  • A free AWS account. You can create one here.
  • A free Pusher account. You can create one here.
  • A free Google Firebase account. You can create one here.
  • Python 3.7.x installed on your local machine. Download here.
  • Android Studio 3.3.2+
  • An understanding of Android development and Android Studio environment.
  • Pip installed on your local machine. Instructions here.
  • Pipenv installed on your local machine. Instructions here.

This tutorial provides a Makefile for Linux and MacOS users to bundle the code. Windows 10 users should use a Linux subsystem or bundle the Lambda code using the instructions here.

Create your Android application

We will need to have a user that has registered for notifications and signed up for an interest we will call “hello”, so we can test out our implementation. We’re going to create a very basic Android app that doesn’t actually show anything to the user except for the notification on the lock screen.

Create a new Empty Activity project using Android Studio and name it something like LambdaPush. Provide a Package name and remember this as you will need it for completing the Firebase set up. We will be using Kotlin as the language choice for this tutorial and supporting Android 16+ (Jelly Bean).

Firebase set up

Log in to your Firebase account here and go to your console. If you do not already have a project created you will need to create one and name it anything you like, if you have a project select it. Within the Project Overview page select Add App and follow the instruction for creating a new Android application.

Once you have completed the setup for your Android app you will be returned to the dashboard. You will need to go to the project settings (found within the “settings cog” in the top left). Once in the project settings select the Cloud Messaging tab. Copy the Server key you will need it for setting up your Pusher Beams instance.

lambda-android-firebase

Creating a Pusher Beams instance

Login or create an account to access your dashboard here. Create a new beams instance using the dashboard.

lambda-android-beams

Complete step one of the Android setup guide, by providing your FCM server key you copied earlier and Continue. We will pick up the remainder later on in this tutorial. Press the X to exit the setup guide and you will be returned to your dashboard for that instance. Scroll to the bottom of the page and you will find your Beams instance ID and secret key, make note of these you will need them later.

Adding the SDKs

Open your app level build.gradle file and add the following into your dependencies:

1// app/build.gradle
2    ...
3    dependencies {
4     ...
5     implementation 'com.google.firebase:firebase-messaging:17.1.0'
6     implementation 'com.pusher:push-notifications-android:1.4.0'
7     ...
8    }
9    ...

Here we are adding the Firebase messaging SDK and the Pusher Beams SDK. You should already have the Google Service SDK and google-services.json added to your project when setting up the Firebase app.

Synchronize Gradle by pressing the Sync Now button.

Initialize Pusher Beams

Open your main activity and add the following import:

    import com.pusher.pushnotifications.PushNotifications

Add the following to your onCreate function:

1PushNotifications.start(applicationContext, "YOUR_INSTANCE_ID")
2    PushNotifications.addDeviceInterest("hello")

Remember to replace YOUR_INSTANCE_ID with the instance id from your Pusher Beams console and run your application.

Create your Lambda function

Writing our function

We will need to install our packages and write our function on our local machine before we can upload it to a Lambda function. Create a new working directory on your local machine and within run the following command in your terminal working directory:

1$ pipenv install pusher_push_notifications
2    $ pipenv install requests

These commands will install our Pusher notifications dependency within our local directory. It also sets up a virtual environment for our project. Next create a new file called index.py and open it in your favorite text editor and add the following code:

1// index.py
2    from pusher_push_notifications import PushNotifications
3    import requests
4    
5    def lambda_handler(event, context):
6        beams_client = PushNotifications(
7                    instance_id='YOUR_INSTANCE_ID',
8                    secret_key='YOUR_SECRET_KEY',
9                    )
10    
11        response = beams_client.publish_to_interests(interests=['hello'],
12                                                 publish_body={
13                                                     'fcm': {
14                                                        'notification': {
15                                                            'title': event['title'],
16                                                            'body': event['message'],
17                                                        },
18                                                     },
19                                                 },
20                                                 )
21        print(response['publishId'])

This code will be used by our Lambda function later on to publish notifications to devices that are registered for the hello interest. We use the event['title'] and event['message'] to form part of the message. We’ll look at this in more detail when we come to test our integration. Remember to replace YOUR_INSTANCE_ID and YOUR_SECRET_KEY with the credentials from your Pusher Beams console.

Next we need to compress the directory we have been working in and make a .zip such that we can upload our code and dependencies to our function later on. Download the Make file from the source code repository here and put it in your working directory. Run the command:

    $ make build

Note: If you are using Windows 10 without a Linux subsystem you should follow the instructions here.

This will create a zip file called Python.zip with all the dependencies packaged within it.

Creating a Lambda function

Log in or create an account to access your AWS console here. Once you are logged in use the search bar to find Lambda and select it from the list.

lambda-android-aws-console

Note: Set your AWS region to N. Virginia in the top right if it is not already.

You should be redirected to the Lambda service and see an option Create Function, select this. Choose the Author from Scratch option at the top of the next page. This will provide us a basic “hello world” template we can use to create our function. Complete the basic setup as shown in the image below.

lambda-android-aws-new-function-python
  • Function name - Name this whatever you want for example “Pusher-Beams-Python”.
  • Runtime - We will be using Python 3.7 so select this from the drop down list.
  • Execution role - Select Create a new role from AWS policy templates. If you already have a role you would rather use you can select Use an existing role.
  • Role name - You can name this anything you like for example “lambda_basic_execution”.
  • Policy templates - You can leave this blank.

Once complete select the Create function button at the bottom of the page. You should be redirected to your Lambda function console once it has been created. We can ignore the Designer section of the console. This area allows us to tie together different AWS services, you may wish to use this with a production function such that it can be accessed from the wider internet. However, we will just be using the test service for the purpose of this tutorial.

Now we need to upload our code. In the Function code section select the Upload a .zip file from the Code entry type dropdown menu. Use the Upload button to search your local machine for the Python.zip we created earlier. Finally change the Handler to be index.lambda_handler, this will allow AWS Lambda to find our function within our folder. If everything looks like the below image click Save in the top right.

lambda-android-aws-function-code-python

Testing our implementation

In the top right of your Lambda console select the Test button. We need to configure a test option. Create a new test event like the below image. Notice how our keys in the JSON object are title and message. These are the event keys we were using in our code to provide the title and body for the push notification.

lambda-android-aws-test-event

Once you are done press the Create button at the bottom. The dialog box will close and the test HelloTest should be selected in the dropdown menu by the Test button, Press Test. If everything has worked as expected you should receive a push to your device and a similar log output from your Lambda console.

lambda-android-aws-test-success
lambda-android-push-notification

Conclusion

We’ve learnt how to create an AWS Lambda function using Python that can publish a push notification using Pusher Beams to an Android device. The source code for this tutorial can be found here.