Hello everyone! In this blog post, I'm gonna talk about how you can actually send a push notification to your Android application with Django from your own app server. First, I'm gonna walk you through the details of how to actually write the code for the Android application from scratch and will help you on how to register your existing Android application to firebase. The main goal of this blog post will be to help you use the PYFCM package to set up push notifications for android with Django.
It will be a two-step process the part 1 will revolve around creating an Android application, which will have following features
So, let's get to it.
First, we will start by creating our own Android application. Now, this part is important because you actually need to have your own Android application to implement push notifications with Django. Creating a full-fledged application will be beyond the scope of the blog, but a simple hello world application will do.
Shoot up your Android studio, and choose a New project. Fill up the basic information and click next till your application gets rendered on the studio. You can choose any activity you want, but I recommend using empty activity for this; just to keep things simple.
I assume you've signed into your google account in your android studio. If not, do it right away. That will make our task a lot easier.
Once your project is loaded, Goto
Tool->Firebase
In the sidebar that gets opened, click on cloud messaging. Select Setup Firebase Cloud Messaging
This will open a sidebar with three options.
Now, when your device gets started for the first time, the Firebase SDK generates a unique identification token, which is used to recognise every device uniquely. Much like your SSN number (for the USA) or Adhar Number (in case of India).
What we need to do later, is to send this token to our app server. That’s where Volley will kick in. Now before we get to that, make sure you have created a new class that extends the
FirebaseInstanceIdService. In this class, you will have to override the onTokenRefresh method. Look at the following example for reference
package com.example.android.djangopushnotification;
import android.content.Context;
import android.content.SharedPreferences;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
// Created by batman on 3/4/18.
public class FcmInstanceIdService extends FirebaseInstanceIdService
{
public void onTokenRefresh()
{
String recent_token = FirebaseInstanceId.getInstance().getToken();
SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences(getString(R.string.FCM_PREF), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(getString(R.string.FCM_TOKEN), recent_token);
editor.commit();
}
}
Also, we will need to extend the FirebaseMessagingService class. This class will be useful in case of handling messages beyond the level of receiving notifications on apps in the background. We will have to create an onMessageReceived method to handle incoming messages. Look at the illustration below for reference.
package com.example.android.djangopushnotification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.support.v4.app.NotificationCompat; import com.google.firebase.messaging.FirebaseMessagingService; import com.google.firebase.messaging.RemoteMessage; // Created by batman on 3/4/18. public class FcmMessagingService extends FirebaseMessagingService { @Override public void onMessageReceived(RemoteMessage remoteMessage) { String title = remoteMessage.getNotification().getTitle(); String message = remoteMessage.getNotification().getBody(); Intent intent = new Intent(this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this); notificationBuilder.setContentTitle(title); notificationBuilder.setContentText(message); notificationBuilder.setSmallIcon(R.mipmap.ic_launcher); notificationBuilder.setAutoCancel(true); notificationBuilder.setContentIntent(pendingIntent); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify(0, notificationBuilder.build()); } }
Till now, we have created our basic app, with the ability to generate a unique Firebase token, we have added a class to view that number also written a class to handle the message notifications.
Now the final part is to integrate Volley into our application. Volley allows ease exchange of data over Http network for the android application.
To start using Volley add the following line inside dependencies in your app level gradle file. compile 'com.mcxiaoke.volley:library:1.0.19'
Now we need a class to implement the Request Queue methods. Look at the example below for help. I’m calling it MySingleton.java. The class has to be a singleton because we will need only one instance of this class at any given time, and this will be achieved by making the constructor private. Keep in mind that you’ll need to edit the server address according to your application server.
package com.example.android.djangopushnotification; import android.content.Context; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.toolbox.Volley; // Created by batman on 3/4/18. public class MySingleton { private static MySingleton mInstance; private static Context mCtx; private RequestQueue requestQueue; private MySingleton(Context context) { mCtx = context; requestQueue = getReqeustQueue(); } private RequestQueue getReqeustQueue() { if(requestQueue==null) { requestQueue = Volley.newRequestQueue(mCtx.getApplicationContext()); } return requestQueue; } public static synchronized MySingleton getmInstance(Context context) { if(mInstance==null) { mInstance = new MySingleton(context); } return mInstance; } public<T> void addToRequestQueue(Request<T> request) { getReqeustQueue().add(request); } }
Now, it’s time to put all of these things together. What we are going to do now is to create a simple button, that when clicked, will send the FCM token to our application server.
I’ve actually attached the code which, when compiled creates a button. This button when clicked sends the token to the app server and displays the response to the user in the form of a dialogue box.
package com.example.android.djangopushnotification; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.android.volley.AuthFailureError; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import java.io.StringReader; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; public class MainActivity extends AppCompatActivity { Button button; TextView textView; String app_server_url = "http://192.168.43.204:8000/insert/?fcm_token="; //change it to your server address AlertDialog.Builder builder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button2); textView = (TextView) findViewById(R.id.textView); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences(getString(R.string.FCM_PREF), Context.MODE_PRIVATE); final String token = sharedPreferences.getString(getString(R.string.FCM_TOKEN), ""); builder = new AlertDialog.Builder(MainActivity.this); textView.setText(token); StringRequest stringRequest = new StringRequest(Request.Method.GET, app_server_url+token, new Response.Listener<String>() { @Override public void onResponse(String response) { builder.setTitle("Server Response"); builder.setMessage("Response: "+response); builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }); AlertDialog alertDialog = builder.create(); alertDialog.show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(MainActivity.this, "Error.."+error.getMessage(), Toast.LENGTH_SHORT).show(); error.printStackTrace(); } }) { protected Map<String, String> getParams() throws AuthFailureError { Map<String, String> params = new HashMap<String, String>(); params.put("fcm_token", token); return params; } }; MySingleton.getmInstance(MainActivity.this).addToRequestQueue(stringRequest); } }); } }
That’s it. Our app is done now. Now it’s time to code our Django server.
We will be using the pyfcm module. To install the module run the command
$ pip3 install pyfcm
Note: You may have to replace pip3 with just pip for some distribution of Linux or windows. Once the module gets installed, we are ready to begin.
Refer to my previous blog post on this link https://www.zeolearn.com/magazine/django-vs-flask-a-comparative-study for help in setting up a simple Hello world program.
After you’ve managed to compile the Hello World in Django, the next step is to create a database to store the fcm ids. We will be using the default sqlite3 database to create a table with only one column currently; that will be called fcm_token.
Open up your Models.py and make the required changes. Use the example shown below for help.
Github gist for Modules.py
<script src="https://gist.github.com/devershichandra27/657e2690610c6fff4dbaf3706e588982.js"></script>
Save the Modules.py, and apply the migrations.
Now, I’m making certain maybe not so obvious assumptions here before taking you forward. First is, there is currently only one device running the app; that means there is only one Firebase Id currently being stored in the database. Second, to send the notifications to the device, you may have to make few changes in this code; as per your own need like the exact URL which when visited should trigger the notification to the application. In my case, the notification gets sent to the application as soon as the user visits <my server’s address>/send. The third assumption is, you’re performing these stunts under the adult supervision. (Just kidding! They are perfectly safe for you)
But, on a sincere note, in case there are multiple devices you wanna send notifications to; I’ll add the required snippet as a comment.
from django.shortcuts import render from django.http import HttpResponse from .models import fcm_info from pyfcm import FCMNotification # Create your views here. #this was the original home page, it declares the list of all the fcmid's in database def homePageView(request): prize = "<h1>Hello There</h1>" tokens = fcm_info.objects.all() for token in tokens: prize += token.fcm_token prize += '<br>' return HttpResponse(prize) #inserting the token into database, after receiving it from Volley def fcm_insert(request): token = request.GET.get("fcm_token", '') a = fcm_info(fcm_token=token) a.save() return HttpResponse(token) #the method which sends the notification def send_notifications(request): path_to_fcm = "https://fcm.googleapis.com" server_key = 'insert your server keys here' reg_id = fcm_info.objects.all()[0].fcm_token #quick and dirty way to get that ONE fcmId from table message_title = "Zeo Learn" message_body = "Hi john, Zeo learn Rocks!" result = FCMNotification(api_key=server_key).notify_single_device(registration_id=reg_id, message_title=message_title, message_body=message_body) return HttpResponse(result) #in case you wanna send notifications to multitple ids in just replace the argument registration_id in the notify_single_device #function with registration_ids and provide it with the list of ids you wanna send notifications to.
I’m also attaching the urls.py for your help Github gist for urls.py
from django.urls import path from django.conf.urls import url from . import views #the home page urlpatterns = [ path('', views.homePageView, name='home'), #the address targetted at the MainActivity.java file. It was the destination where Volley has to send data path(r'insert/', views.fcm_insert, name='insert'), #for sending the notification path(r'send/', views.send_notifications, name='send') ]
In conclusion, we were able to create push notification server for Android app using Django framework written in Python.
Leave a Reply
Your email address will not be published. Required fields are marked *