Android Push Notifications using Firebase Cloud Messaging FCM & PHP
source link: https://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Android Push Notifications using Firebase Cloud Messaging FCM & PHP
By Ravi Tamada July 12, 2017 2,731 CommentsIn recent times, Google moved from Google Cloud Messaging (GCM) to Firebase Cloud Messaging (FCM). Just like GCM, FCM is a cross-platform messaging solution that allows you to send messages. FCM is completely free and there are no limitations.
If you have followed any of my previous tutorials about GCM, I strongly recommend you migrate to Firebase today itself. In this article we learn the features of firebase cloud messaging by building a simple app. We’ll also learn how to integrate firebase to your backend, so that you can send the messages from your server.
1. Firebase Message types
Using Firebase Cloud Messaging you can send three types of messages i.e Notification Message, Data Message and message with both Notification & Data Payload.
1.1 Notification Message:
Notification messages are handled by firebase SDK itself. Typically the notification message contains title, message, icon etc., These message can be sent from firebase console UI. By sending this kind of messages, you won’t get much control over the notification. The notification will be shown automatically when the app is in background.
In order to send notification message, you need to use notification key in json data. An example of notification message is given below.
{
"to"
:
"e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak..."
,
"notification"
: {
"body"
:
"Cool offers. Get them before expiring!"
,
"title"
:
"Flat 80% discount"
,
"icon"
:
"appicon"
}
}
1.2 Data Message:
Data messages has to be handled by the android app. You can add this kind of messages if you want to send some additional data along with the notification. But sending these messages through firebase console is not possible. You need to have a server side logic to send the notification using Firebase API. You need to use data key when sending this message.
An example of data message json is given below.
{
"to"
:
"e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak..."
,
"data"
: {
"name"
:
"LG LED TV S15"
,
"product_id"
:
"123"
,
"final_price"
:
"2500"
}
}
1.3 Messages with both notification and data payload:
A message can also contains both notification and data payload. When these kind of messages are sent, it will be handled in two scenarios depending upon app state (background / foreground). For these message we can use both notification and data keys.
When in the background – Apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification.
When in the foreground – App receives a message object with both payloads available.
An example of notification & data payload message will be
{
"to"
:
"e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak..."
,
"notification"
: {
"body"
:
"Cool offers. Get them before expiring!"
,
"title"
:
"Flat 80% discount"
,
"icon"
:
"appicon"
},
"data"
: {
"name"
:
"LG LED TV S15"
,
"product_id"
:
"123"
,
"final_price"
:
"2500"
}
}
2. Message Targeting
While sending message using firebase, you can choose the targeted audience. You can send either to a single user or to group of users using a topic name.
2.1 Sending to Single User
When a single user targeted, the firebase registration id is used to identify the device. The reg id has to be mentioned in to filed of json.
{
"to"
:
"e1w6hEbZn-8:APA91bEUIb2JewYCIiApsMu5JfI5Ak..."
,
"data"
: {
"message"
:
"This is a Firebase Cloud Messaging Topic Message!"
,
}
}
2.2 Topic Messaging
Topic messaging is useful when segment of users targeted for messaging. For this all the users has to subscribe to firebase topic. Ex: When you want to send message to all the users who are engaged with news, you can create a topic named news and send notification to news topic.
The request format of topic messaging is given below. In the to filed you need to mention the topic name.
{
"to"
:
"/topics/news"
,
"data"
: {
"message"
:
"This is a Firebase Cloud Messaging Topic Message!"
,
}
}
3. Integrating Firebase Cloud Messaging
I hope the above information gave you good overview of firebase features and the options they are providing. Now we’ll create a simple app that receives firebase messages from both firebase console and from the PHP code.
1. First thing you need to do is go to https://firebase.google.com/ and make an account to gain access to their console. After you gain access to the console you can start by creating your first project.
2. Give the package name of your project (mine is info.androidhive.firebasenotifications) in which you are going to integrate the Firebase. Here the google-services.json file will be downloaded when you press add app button.
3. Create a new project in Android Studio from File ⇒ New Project. While filling the project details, use the same package name which you gave in firebase console. In my case I am using same info.androidhive.firebasenotifications.
4. Paste the google-services.json file to your project’s app folder. This step is very important as your project won’t build without this file.
5. Now open the build.gradle located in project’s home directory and add firebase dependency.
dependencies {
classpath
'com.android.tools.build:gradle:2.2.0-rc1'
classpath
'com.google.gms:google-services:3.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
6. Open app/build.gradle and add firebase messaging dependency. At the very bottom of the file, add apply plugin: ‘com.google.gms.google-services’
dependencies {
compile
'com.google.firebase:firebase-messaging:9.6.0'
}
apply plugin:
'com.google.gms.google-services'
7. Create three packages named activity, app, service and utils under your project folder. Below is the structure and files required for this project.
8. Download notification.mp3 and place it in res ⇒ raw folder. This step is optional, but if you want to play a custom notification sound when notification received.
9. Create a class named Config.java under app package. This class contains all the constant values that we use across the app.
package
info.androidhive.firebasenotifications.app;
public
class
Config {
// global topic to receive app wide push notifications
public
static
final
String TOPIC_GLOBAL =
"global"
;
// broadcast receiver intent filters
public
static
final
String REGISTRATION_COMPLETE =
"registrationComplete"
;
public
static
final
String PUSH_NOTIFICATION =
"pushNotification"
;
// id to handle the notification in the notification tray
public
static
final
int
NOTIFICATION_ID =
100
;
public
static
final
int
NOTIFICATION_ID_BIG_IMAGE =
101
;
public
static
final
String SHARED_PREF =
"ah_firebase"
;
}
10. Create a class named NotificationUtils.java under utils package. This class contains necessary functions required to show the message (with title, message, image and timestamp) in notification tray.
package
info.androidhive.firebasenotifications.util;
import
android.app.ActivityManager;
import
android.app.Notification;
import
android.app.NotificationManager;
import
android.app.PendingIntent;
import
android.content.ComponentName;
import
android.content.ContentResolver;
import
android.content.Context;
import
android.content.Intent;
import
android.graphics.Bitmap;
import
android.graphics.BitmapFactory;
import
android.media.Ringtone;
import
android.media.RingtoneManager;
import
android.net.Uri;
import
android.os.Build;
import
android.support.v4.app.NotificationCompat;
import
android.text.Html;
import
android.text.TextUtils;
import
android.util.Patterns;
import
java.io.IOException;
import
java.io.InputStream;
import
java.net.HttpURLConnection;
import
java.net.URL;
import
java.text.ParseException;
import
java.text.SimpleDateFormat;
import
java.util.Date;
import
java.util.List;
import
info.androidhive.firebasenotifications.R;
import
info.androidhive.firebasenotifications.app.Config;
/**
* Created by Ravi on 31/03/15.
*/
public
class
NotificationUtils {
private
static
String TAG = NotificationUtils.
class
.getSimpleName();
private
Context mContext;
public
NotificationUtils(Context mContext) {
this
.mContext = mContext;
}
public
void
showNotificationMessage(String title, String message, String timeStamp, Intent intent) {
showNotificationMessage(title, message, timeStamp, intent,
null
);
}
public
void
showNotificationMessage(
final
String title,
final
String message,
final
String timeStamp, Intent intent, String imageUrl) {
// Check for empty push message
if
(TextUtils.isEmpty(message))
return
;
// notification icon
final
int
icon = R.mipmap.ic_launcher;
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
mContext,
0
,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
);
final
NotificationCompat.Builder mBuilder =
new
NotificationCompat.Builder(
mContext);
final
Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+
"://"
+ mContext.getPackageName() +
"/raw/notification"
);
if
(!TextUtils.isEmpty(imageUrl)) {
if
(imageUrl !=
null
&& imageUrl.length() >
4
&& Patterns.WEB_URL.matcher(imageUrl).matches()) {
Bitmap bitmap = getBitmapFromURL(imageUrl);
if
(bitmap !=
null
) {
showBigNotification(bitmap, mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
}
else
{
showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
}
}
}
else
{
showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
playNotificationSound();
}
}
private
void
showSmallNotification(NotificationCompat.Builder mBuilder,
int
icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
NotificationCompat.InboxStyle inboxStyle =
new
NotificationCompat.InboxStyle();
inboxStyle.addLine(message);
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(
0
)
.setAutoCancel(
true
)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(inboxStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(Config.NOTIFICATION_ID, notification);
}
private
void
showBigNotification(Bitmap bitmap, NotificationCompat.Builder mBuilder,
int
icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
NotificationCompat.BigPictureStyle bigPictureStyle =
new
NotificationCompat.BigPictureStyle();
bigPictureStyle.setBigContentTitle(title);
bigPictureStyle.setSummaryText(Html.fromHtml(message).toString());
bigPictureStyle.bigPicture(bitmap);
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(
0
)
.setAutoCancel(
true
)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(bigPictureStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(Config.NOTIFICATION_ID_BIG_IMAGE, notification);
}
/**
* Downloading push notification image before displaying it in
* the notification tray
*/
public
Bitmap getBitmapFromURL(String strURL) {
try
{
URL url =
new
URL(strURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(
true
);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return
myBitmap;
}
catch
(IOException e) {
e.printStackTrace();
return
null
;
}
}
// Playing notification sound
public
void
playNotificationSound() {
try
{
Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+
"://"
+ mContext.getPackageName() +
"/raw/notification"
);
Ringtone r = RingtoneManager.getRingtone(mContext, alarmSound);
r.play();
}
catch
(Exception e) {
e.printStackTrace();
}
}
/**
* Method checks if the app is in background or not
*/
public
static
boolean
isAppIsInBackground(Context context) {
boolean
isInBackground =
true
;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if
(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
for
(ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if
(processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
for
(String activeProcess : processInfo.pkgList) {
if
(activeProcess.equals(context.getPackageName())) {
isInBackground =
false
;
}
}
}
}
}
else
{
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(
1
);
ComponentName componentInfo = taskInfo.get(
0
).topActivity;
if
(componentInfo.getPackageName().equals(context.getPackageName())) {
isInBackground =
false
;
}
}
return
isInBackground;
}
// Clears notification tray messages
public
static
void
clearNotifications(Context context) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
}
public
static
long
getTimeMilliSec(String timeStamp) {
SimpleDateFormat format =
new
SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss"
);
try
{
Date date = format.parse(timeStamp);
return
date.getTime();
}
catch
(ParseException e) {
e.printStackTrace();
}
return
0
;
}
}
11. Create a class named MyFirebaseInstanceIDService.java under service package. This class receives the firebase registration id which will be unique to each app. This registration id is needed when you want to send message to a single device. You can send this token to your server app to send notification to devices later.
onTokenRefresh() method will be called whenever there is a change in firebase registration id.
storeRegIdInPref() stores the registration id in shared preferences.
LocalBroadcastManager – Broadcast manager broadcasts the reg id to all the activities those are listening.
package
info.androidhive.firebasenotifications.service;
import
android.content.Intent;
import
android.content.SharedPreferences;
import
android.support.v4.content.LocalBroadcastManager;
import
android.util.Log;
import
com.google.firebase.iid.FirebaseInstanceId;
import
com.google.firebase.iid.FirebaseInstanceIdService;
import
info.androidhive.firebasenotifications.app.Config;
/**
* Created by Ravi Tamada on 08/08/16.
* www.androidhive.info
*/
public
class
MyFirebaseInstanceIDService
extends
FirebaseInstanceIdService {
private
static
final
String TAG = MyFirebaseInstanceIDService.
class
.getSimpleName();
@Override
public
void
onTokenRefresh() {
super
.onTokenRefresh();
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// Saving reg id to shared preferences
storeRegIdInPref(refreshedToken);
// sending reg id to your server
sendRegistrationToServer(refreshedToken);
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete =
new
Intent(Config.REGISTRATION_COMPLETE);
registrationComplete.putExtra(
"token"
, refreshedToken);
LocalBroadcastManager.getInstance(
this
).sendBroadcast(registrationComplete);
}
private
void
sendRegistrationToServer(
final
String token) {
// sending gcm token to server
Log.e(TAG,
"sendRegistrationToServer: "
+ token);
}
private
void
storeRegIdInPref(String token) {
SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF,
0
);
SharedPreferences.Editor editor = pref.edit();
editor.putString(
"regId"
, token);
editor.commit();
}
}
12. Create another class named MyFirebaseMessagingService.java under service package. This class receives the firebase messages into onMessageReceived() method.
> When notification type message is sent, firebase automatically shows the notification when the app is in background. If the app is in foreground, handleNotification() method handles the notification message.
> When data type message is sent, handleDataMessage() method is used to handle the payload irrespective of app state (foreground / background).
> LocalBroadcastManager is used to broadcast the message to all the activities which are registered for the broadcast receiver.
package
info.androidhive.firebasenotifications.service;
import
android.content.Context;
import
android.content.Intent;
import
android.support.v4.content.LocalBroadcastManager;
import
android.text.TextUtils;
import
android.util.Log;
import
com.google.firebase.messaging.FirebaseMessagingService;
import
com.google.firebase.messaging.RemoteMessage;
import
org.json.JSONException;
import
org.json.JSONObject;
import
info.androidhive.firebasenotifications.activity.MainActivity;
import
info.androidhive.firebasenotifications.app.Config;
import
info.androidhive.firebasenotifications.util.NotificationUtils;
/**
* Created by Ravi Tamada on 08/08/16.
* www.androidhive.info
*/
public
class
MyFirebaseMessagingService
extends
FirebaseMessagingService {
private
static
final
String TAG = MyFirebaseMessagingService.
class
.getSimpleName();
private
NotificationUtils notificationUtils;
@Override
public
void
onMessageReceived(RemoteMessage remoteMessage) {
Log.e(TAG,
"From: "
+ remoteMessage.getFrom());
if
(remoteMessage ==
null
)
return
;
// Check if message contains a notification payload.
if
(remoteMessage.getNotification() !=
null
) {
Log.e(TAG,
"Notification Body: "
+ remoteMessage.getNotification().getBody());
handleNotification(remoteMessage.getNotification().getBody());
}
// Check if message contains a data payload.
if
(remoteMessage.getData().size() >
0
) {
Log.e(TAG,
"Data Payload: "
+ remoteMessage.getData().toString());
try
{
JSONObject json =
new
JSONObject(remoteMessage.getData().toString());
handleDataMessage(json);
}
catch
(Exception e) {
Log.e(TAG,
"Exception: "
+ e.getMessage());
}
}
}
private
void
handleNotification(String message) {
if
(!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification =
new
Intent(Config.PUSH_NOTIFICATION);
pushNotification.putExtra(
"message"
, message);
LocalBroadcastManager.getInstance(
this
).sendBroadcast(pushNotification);
// play notification sound
NotificationUtils notificationUtils =
new
NotificationUtils(getApplicationContext());
notificationUtils.playNotificationSound();
}
else
{
// If the app is in background, firebase itself handles the notification
}
}
private
void
handleDataMessage(JSONObject json) {
Log.e(TAG,
"push json: "
+ json.toString());
try
{
JSONObject data = json.getJSONObject(
"data"
);
String title = data.getString(
"title"
);
String message = data.getString(
"message"
);
boolean
isBackground = data.getBoolean(
"is_background"
);
String imageUrl = data.getString(
"image"
);
String timestamp = data.getString(
"timestamp"
);
JSONObject payload = data.getJSONObject(
"payload"
);
Log.e(TAG,
"title: "
+ title);
Log.e(TAG,
"message: "
+ message);
Log.e(TAG,
"isBackground: "
+ isBackground);
Log.e(TAG,
"payload: "
+ payload.toString());
Log.e(TAG,
"imageUrl: "
+ imageUrl);
Log.e(TAG,
"timestamp: "
+ timestamp);
if
(!NotificationUtils.isAppIsInBackground(getApplicationContext())) {
// app is in foreground, broadcast the push message
Intent pushNotification =
new
Intent(Config.PUSH_NOTIFICATION);
pushNotification.putExtra(
"message"
, message);
LocalBroadcastManager.getInstance(
this
).sendBroadcast(pushNotification);
// play notification sound
NotificationUtils notificationUtils =
new
NotificationUtils(getApplicationContext());
notificationUtils.playNotificationSound();
}
else
{
// app is in background, show the notification in notification tray
Intent resultIntent =
new
Intent(getApplicationContext(), MainActivity.
class
);
resultIntent.putExtra(
"message"
, message);
// check for image attachment
if
(TextUtils.isEmpty(imageUrl)) {
showNotificationMessage(getApplicationContext(), title, message, timestamp, resultIntent);
}
else
{
// image is present, show notification with image
showNotificationMessageWithBigImage(getApplicationContext(), title, message, timestamp, resultIntent, imageUrl);
}
}
}
catch
(JSONException e) {
Log.e(TAG,
"Json Exception: "
+ e.getMessage());
}
catch
(Exception e) {
Log.e(TAG,
"Exception: "
+ e.getMessage());
}
}
/**
* Showing notification with text only
*/
private
void
showNotificationMessage(Context context, String title, String message, String timeStamp, Intent intent) {
notificationUtils =
new
NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent);
}
/**
* Showing notification with text and image
*/
private
void
showNotificationMessageWithBigImage(Context context, String title, String message, String timeStamp, Intent intent, String imageUrl) {
notificationUtils =
new
NotificationUtils(context);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
notificationUtils.showNotificationMessage(title, message, timeStamp, intent, imageUrl);
}
}
13. Open AndroidManifest.xml and add the two firebase services MyFirebaseMessagingService and MyFirebaseInstanceIDService.
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
package
=
"info.androidhive.firebasenotifications"
>
<
application
android:allowBackup
=
"true"
android:icon
=
"@mipmap/ic_launcher"
android:label
=
"@string/app_name"
android:supportsRtl
=
"true"
android:theme
=
"@style/AppTheme"
>
<
activity
android:name
=
".activity.MainActivity"
android:label
=
"@string/title_main_activity"
>
<
intent-filter
>
<
action
android:name
=
"android.intent.action.MAIN"
/>
<
category
android:name
=
"android.intent.category.LAUNCHER"
/>
</
intent-filter
>
</
activity
>
<!-- Firebase Notifications -->
<
service
android:name
=
".service.MyFirebaseMessagingService"
>
<
intent-filter
>
<
action
android:name
=
"com.google.firebase.MESSAGING_EVENT"
/>
</
intent-filter
>
</
service
>
<
service
android:name
=
".service.MyFirebaseInstanceIDService"
>
<
intent-filter
>
<
action
android:name
=
"com.google.firebase.INSTANCE_ID_EVENT"
/>
</
intent-filter
>
</
service
>
<!-- ./Firebase Notifications -->
</
application
>
</
manifest
>
14. Finally we need to modify our main activity to display the incoming messages on the screen. Open layout file of main activity activity_main.xml and modify the layout as below.
<?
xml
version
=
"1.0"
encoding
=
"utf-8"
?>
android:id
=
"@+id/activity_main"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:paddingBottom
=
"@dimen/activity_vertical_margin"
android:paddingLeft
=
"@dimen/activity_horizontal_margin"
android:paddingRight
=
"@dimen/activity_horizontal_margin"
android:paddingTop
=
"@dimen/activity_vertical_margin"
tools:context
=
"info.androidhive.firebasenotifications.activity.MainActivity"
>
<
TextView
android:id
=
"@+id/txt_push_message"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_alignParentTop
=
"true"
android:layout_centerHorizontal
=
"true"
android:layout_marginTop
=
"40dp"
android:gravity
=
"center_horizontal"
android:textColor
=
"@color/colorPrimary"
android:textSize
=
"26dp"
/>
<
TextView
android:id
=
"@+id/txt_reg_id"
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:layout_alignParentBottom
=
"true"
/>
</
RelativeLayout
>
15. Open MainActivity.java and do the below necessary changes. Here in onResume() method we are registering the broadcast receivers. So that this activity gets the push messages and registration id.
displayFirebaseRegId() fetches the firebase registration id from shared preferences and displays it on the screen. This is just for your references, we don’t use the reg id any where in the app.
Subscribing to Topic
When you want to subscribe to any topic, subscribeToTopic() function can be used. When a client app subscribes to a new topic name (one that does not already exist for your Firebase project), a new topic of that name is created in FCM and any client can subsequently subscribe to it.
FirebaseMessaging.getInstance().subscribeToTopic(
'news'
);
Unsubscribing from Topic
Similarly the client can unsubscribe from a topic by calling unsubscribeFromTopic() method.
FirebaseMessaging.getInstance().unsubscribeFromTopic(
'news'
);
package
info.androidhive.firebasenotifications.activity;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.content.IntentFilter;
import
android.content.SharedPreferences;
import
android.os.Bundle;
import
android.support.v4.content.LocalBroadcastManager;
import
android.support.v7.app.AppCompatActivity;
import
android.text.TextUtils;
import
android.util.Log;
import
android.widget.TextView;
import
android.widget.Toast;
import
com.google.firebase.messaging.FirebaseMessaging;
import
info.androidhive.firebasenotifications.R;
import
info.androidhive.firebasenotifications.app.Config;
import
info.androidhive.firebasenotifications.util.NotificationUtils;
public
class
MainActivity
extends
AppCompatActivity {
private
static
final
String TAG = MainActivity.
class
.getSimpleName();
private
BroadcastReceiver mRegistrationBroadcastReceiver;
private
TextView txtRegId, txtMessage;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtRegId = (TextView) findViewById(R.id.txt_reg_id);
txtMessage = (TextView) findViewById(R.id.txt_push_message);
mRegistrationBroadcastReceiver =
new
BroadcastReceiver() {
@Override
public
void
onReceive(Context context, Intent intent) {
// checking for type intent filter
if
(intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
// gcm successfully registered
// now subscribe to `global` topic to receive app wide notifications
FirebaseMessaging.getInstance().subscribeToTopic(Config.TOPIC_GLOBAL);
displayFirebaseRegId();
}
else
if
(intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
// new push notification is received
String message = intent.getStringExtra(
"message"
);
Toast.makeText(getApplicationContext(),
"Push notification: "
+ message, Toast.LENGTH_LONG).show();
txtMessage.setText(message);
}
}
};
displayFirebaseRegId();
}
// Fetches reg id from shared preferences
// and displays on the screen
private
void
displayFirebaseRegId() {
SharedPreferences pref = getApplicationContext().getSharedPreferences(Config.SHARED_PREF,
0
);
String regId = pref.getString(
"regId"
,
null
);
Log.e(TAG,
"Firebase reg id: "
+ regId);
if
(!TextUtils.isEmpty(regId))
txtRegId.setText(
"Firebase Reg Id: "
+ regId);
else
txtRegId.setText(
"Firebase Reg Id is not received yet!"
);
}
@Override
protected
void
onResume() {
super
.onResume();
// register GCM registration complete receiver
LocalBroadcastManager.getInstance(
this
).registerReceiver(mRegistrationBroadcastReceiver,
new
IntentFilter(Config.REGISTRATION_COMPLETE));
// register new push message receiver
// by doing this, the activity will be notified each time a new message arrives
LocalBroadcastManager.getInstance(
this
).registerReceiver(mRegistrationBroadcastReceiver,
new
IntentFilter(Config.PUSH_NOTIFICATION));
// clear the notification area when the app is opened
NotificationUtils.clearNotifications(getApplicationContext());
}
@Override
protected
void
onPause() {
LocalBroadcastManager.getInstance(
this
).unregisterReceiver(mRegistrationBroadcastReceiver);
super
.onPause();
}
}
Now we have completed the integration of firebase cloud messaging. In order to verify it, run the project and you should see the firebase reg id on the screen. You can also find the reg id in LogCat.
4. Sending Messages from Firebase Console
Now we’ll send the first message from firebase console. Go to firebase console and click on Notifications in left menu. You will get an interface where you can type the message, select the targeting and send the message.
5. Sending Messages from PHP Backend
Sending message from firebase console is not always an optimal solution for lot of apps. Huge number of apps requires an automatic notification to user whenever there is an event, which is not possible using firebase console. To overcome this problem you need to integrate the firebase API from your backend server.
Let’s create a simple PHP project to send the messages from backend. I am assuming you are having basic knowledge of PHP and WAMP. If you are new you can get the help from this article.
5.1 Obtaining your Firebase Server API Key
Firebase provides Server API Key to identify your firebase app. To obtain your Server API Key, goto firebase console, select the project and goto settings, select Cloud Messaging tab and copy your Server key.
1. Goto your WAMP directory and create new folder named firebase inside htdocs or www.
2. Create a file named config.php and add the below code. Here we define the firebase Server API Key to send request to firebase endpoint.
<?php
// Firebase API Key
define(
'FIREBASE_API_KEY'
,
'AAAA4qJeE5A:APA91bGct--6lGrYwgBC8iz5reyx4qPUB7ByXX8MwC7Vcs8u...'
);
3. Create a file named push.php This class prepares and the push notification json that needs to be send to firebase.
<?php
/**
* @author Ravi Tamada
* @link URL Tutorial link
*/
class
Push {
// push message title
private
$title
;
private
$message
;
private
$image
;
// push message payload
private
$data
;
// flag indicating whether to show the push
// notification or not
// this flag will be useful when perform some opertation
// in background when push is recevied
private
$is_background
;
function
__construct() {
}
public
function
setTitle(
$title
) {
$this
->title =
$title
;
}
public
function
setMessage(
$message
) {
$this
->message =
$message
;
}
public
function
setImage(
$imageUrl
) {
$this
->image =
$imageUrl
;
}
public
function
setPayload(
$data
) {
$this
->data =
$data
;
}
public
function
setIsBackground(
$is_background
) {
$this
->is_background =
$is_background
;
}
public
function
getPush() {
$res
=
array
();
$res
[
'data'
][
'title'
] =
$this
->title;
$res
[
'data'
][
'is_background'
] =
$this
->is_background;
$res
[
'data'
][
'message'
] =
$this
->message;
$res
[
'data'
][
'image'
] =
$this
->image;
$res
[
'data'
][
'payload'
] =
$this
->data;
$res
[
'data'
][
'timestamp'
] =
date
(
'Y-m-d G:i:s'
);
return
$res
;
}
}
4. Create a file named firebase.php and add the below code. This class contains necessary functions to send message to firebase api by making a CURL request.
<?php
/**
* @author Ravi Tamada
* @link URL Tutorial link
*/
class
Firebase {
// sending push message to single user by firebase reg id
public
function
send(
$to
,
$message
) {
$fields
=
array
(
'to'
=>
$to
,
'data'
=>
$message
,
);
return
$this
->sendPushNotification(
$fields
);
}
// Sending message to a topic by topic name
public
function
sendToTopic(
$to
,
$message
) {
$fields
=
array
(
'to'
=>
'/topics/'
.
$to
,
'data'
=>
$message
,
);
return
$this
->sendPushNotification(
$fields
);
}
// sending push message to multiple users by firebase registration ids
public
function
sendMultiple(
$registration_ids
,
$message
) {
$fields
=
array
(
'to'
=>
$registration_ids
,
'data'
=>
$message
,
);
return
$this
->sendPushNotification(
$fields
);
}
// function makes curl request to firebase servers
private
function
sendPushNotification(
$fields
) {
require_once
__DIR__ .
'/config.php'
;
// Set POST variables
$headers
=
array
(
'Authorization: key='
. FIREBASE_API_KEY,
'Content-Type: application/json'
);
// Open connection
$ch
= curl_init();
// Set the url, number of POST vars, POST data
curl_setopt(
$ch
, CURLOPT_URL,
$url
);
curl_setopt(
$ch
, CURLOPT_POST, true);
curl_setopt(
$ch
, CURLOPT_HTTPHEADER,
$headers
);
curl_setopt(
$ch
, CURLOPT_RETURNTRANSFER, true);
// Disabling SSL Certificate support temporarly
curl_setopt(
$ch
, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt(
$ch
, CURLOPT_POSTFIELDS, json_encode(
$fields
));
// Execute post
$result
= curl_exec(
$ch
);
if
(
$result
=== FALSE) {
die
(
'Curl failed: '
. curl_error(
$ch
));
}
// Close connection
curl_close(
$ch
);
return
$result
;
}
}
?>
5. Finally create a index.php and add the below code. Here we are creating a simple UI which takes the input and send the notification to android device.
<html>
<head>
<title>AndroidHive | Firebase Cloud Messaging</title>
<meta charset=
"UTF-8"
>
<meta name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<link rel=
"shortcut icon"
href=
"//www.gstatic.com/mobilesdk/160503_mobilesdk/logo/favicon.ico"
>
<style type=
"text/css"
>
body{
}
div.container{
width: 1000px;
margin: 0 auto;
position: relative;
}
legend{
font-size: 30px;
color: #555;
}
.btn_send{
background: #00bcd4;
}
label{
margin:10px 0px !important;
}
textarea{
resize: none !important;
}
.fl_window{
width: 400px;
position: absolute;
right: 0;
top:100px;
}
pre, code {
padding:10px 0px;
box-sizing:border-box;
-moz-box-sizing:border-box;
webkit-box-sizing:border-box;
display:block;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap:
break
-word;
width:100%; overflow-x:auto;
}
</style>
</head>
<body>
<?php
// Enabling error reporting
error_reporting
(-1);
ini_set
(
'display_errors'
,
'On'
);
require_once
__DIR__ .
'/firebase.php'
;
require_once
__DIR__ .
'/push.php'
;
$firebase
=
new
Firebase();
$push
=
new
Push();
// optional payload
$payload
=
array
();
$payload
[
'team'
] =
'India'
;
$payload
[
'score'
] =
'5.6'
;
// notification title
$title
= isset(
$_GET
[
'title'
]) ?
$_GET
[
'title'
] :
''
;
// notification message
$message
= isset(
$_GET
[
'message'
]) ?
$_GET
[
'message'
] :
''
;
// push type - single user / topic
$push_type
= isset(
$_GET
[
'push_type'
]) ?
$_GET
[
'push_type'
] :
''
;
// whether to include to image or not
$include_image
= isset(
$_GET
[
'include_image'
]) ? TRUE : FALSE;
$push
->setTitle(
$title
);
$push
->setMessage(
$message
);
if
(
$include_image
) {
}
else
{
$push
->setImage(
''
);
}
$push
->setIsBackground(FALSE);
$push
->setPayload(
$payload
);
$json
=
''
;
$response
=
''
;
if
(
$push_type
==
'topic'
) {
$json
=
$push
->getPush();
$response
=
$firebase
->sendToTopic(
'global'
,
$json
);
}
else
if
(
$push_type
==
'individual'
) {
$json
=
$push
->getPush();
$regId
= isset(
$_GET
[
'regId'
]) ?
$_GET
[
'regId'
] :
''
;
$response
=
$firebase
->send(
$regId
,
$json
);
}
?>
<div
class
=
"container"
>
<div
class
=
"fl_window"
>
<div><img src=
"https://api.androidhive.info/images/firebase_logo.png"
width=
"200"
alt=
"Firebase"
/></div>
<br/>
<?php
if
(
$json
!=
''
) { ?>
<label><b>Request:</b></label>
<div
class
=
"json_preview"
>
<pre><?php
echo
json_encode(
$json
) ?></pre>
</div>
<?php } ?>
<br/>
<?php
if
(
$response
!=
''
) { ?>
<label><b>Response:</b></label>
<div
class
=
"json_preview"
>
<pre><?php
echo
json_encode(
$response
) ?></pre>
</div>
<?php } ?>
</div>
<form
class
=
"pure-form pure-form-stacked"
method=
"get"
>
<fieldset>
<legend>Send to Single Device</legend>
<label
for
=
"redId"
>Firebase Reg Id</label>
<input type=
"text"
id=
"redId"
name=
"regId"
class
=
"pure-input-1-2"
placeholder=
"Enter firebase registration id"
>
<label
for
=
"title"
>Title</label>
<input type=
"text"
id=
"title"
name=
"title"
class
=
"pure-input-1-2"
placeholder=
"Enter title"
>
<label
for
=
"message"
>Message</label>
<textarea
class
=
"pure-input-1-2"
rows=
"5"
name=
"message"
id=
"message"
placeholder=
"Notification message!"
></textarea>
<label
for
=
"include_image"
class
=
"pure-checkbox"
>
<input name=
"include_image"
id=
"include_image"
type=
"checkbox"
> Include image
</label>
<input type=
"hidden"
name=
"push_type"
value=
"individual"
/>
<button type=
"submit"
class
=
"pure-button pure-button-primary btn_send"
>Send</button>
</fieldset>
</form>
<br/><br/><br/><br/>
<form
class
=
"pure-form pure-form-stacked"
method=
"get"
>
<fieldset>
<legend>Send to Topic `
global
`</legend>
<label
for
=
"title1"
>Title</label>
<input type=
"text"
id=
"title1"
name=
"title"
class
=
"pure-input-1-2"
placeholder=
"Enter title"
>
<label
for
=
"message1"
>Message</label>
<textarea
class
=
"pure-input-1-2"
name=
"message"
id=
"message1"
rows=
"5"
placeholder=
"Notification message!"
></textarea>
<label
for
=
"include_image1"
class
=
"pure-checkbox"
>
<input id=
"include_image1"
name=
"include_image"
type=
"checkbox"
> Include image
</label>
<input type=
"hidden"
name=
"push_type"
value=
"topic"
/>
<button type=
"submit"
class
=
"pure-button pure-button-primary btn_send"
>Send to Topic</button>
</fieldset>
</form>
</div>
</body>
</html>
6. Access the project from your http://localhost/firebase url. (If your apache is running on a port, access the url using port number)
6. Demo
If you are new to PHP and facing any issue while running the above PHP project, you can access the same project here. The UI is same as explained above except few changes. You need to provide your own firebase Server API Key to test your app. Check the video to know how to use the demo page. Don’t worry about exposing your Server API Key, your data is not stored in any manner in the demo page.
Hi there! I am Founder at androidhive and programming enthusiast. My skills includes Android, iOS, PHP, Ruby on Rails and lot more. If you have any idea that you would want me to develop? Let’s talk: [email protected]
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK