I have a function that triggers the date to the firebase database node and sending notification when user inputs data to the android device. I want to to schedule timer to send this notification using an external cron job.I have the code below that successfully sends notification as soon as the user enters the date. Can any one help me please as I'm finding really hard to understand it.What do I have to modify to make it work?
This is the index.js
var functions = require('firebase-functions');
var admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotification = functions.database.ref('/Users/{userId}/description/{descId}')
.onWrite(event => {
// Grab the current value of what was written to the Realtime Database.
var eventSnapshot = event.data;
var str1 = "Your profile title is ";
var str2 = "Date is ";
var strProfile = str1.concat(eventSnapshot.child("title").val());
var strStatus = str2.concat(eventSnapshot.child("date").val());
console.log(strProfile);
console.log(strStatus)
var topic = "android";
var payload = {
data: {
title: eventSnapshot.child("title").val(),
date: eventSnapshot.child("date").val()
}
};
// Send a message to devices subscribed to the provided topic.
return admin.messaging().sendToTopic(topic, payload)
.then(function (response) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message:", response);
})
.catch(function (error) {
console.log("Error sending message:", error);
});
});
MyFirebaseMessagingService Activity
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
showNotification(remoteMessage.getData().get("title"), remoteMessage.getData().get("date"));
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
}
}
private void showNotification(String title, String date) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle("title is " + title)
.setSmallIcon(R.drawable.alex)
.setContentText("your deadline date is " + date)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
You can easily achieve this with the help of AlarmManager. When user inputs a date, get that date and set an Alarm for that specific date and time like this:
Calendar cur_cal = new GregorianCalendar();
cur_cal.setTimeInMillis(System.currentTimeMillis());//set the current time and date for this calendar
Calendar cal = new GregorianCalendar();
cal.add(Calendar.DAY_OF_YEAR, cur_cal.get(Calendar.DAY_OF_YEAR));
cal.set(Calendar.HOUR_OF_DAY, 18);
cal.set(Calendar.MINUTE, 32);
cal.set(Calendar.SECOND, cur_cal.get(Calendar.SECOND));
cal.set(Calendar.MILLISECOND, cur_cal.get(Calendar.MILLISECOND));
cal.set(Calendar.DATE, cur_cal.get(Calendar.DATE));
cal.set(Calendar.MONTH, cur_cal.get(Calendar.MONTH));
Intent intent = new Intent(ProfileList.this,
IntentBroadcastedReceiver.class);
PendingIntent pintent = PendingIntent.getService(ProfileList.this, 0, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pintent);
Then you have to set up a Broadcast Receiver to handle the event. In onReceive() method of your Broadcast Receiver, you will call your web-service to send the request to your server.
public class MyBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent) {
// Call your web-service here.
}
}
Don't forget to define receiver in manifest:
<receiver android:name=".MyBroadcastReceiver" >
Related
This is my first question. I have connected my domain into firebase. The push notification is working when I update the post in my Wordpress Blog. Ok, thats good for now. But, i want to save all that notification in a Fragment, and can be clicked from there to start an activity for post id. How to save that Notification?
Here is my Firebase Messaging code:
private static int VIBRATION_TIME = 500; // in millisecond
private SharedPref sharedPref;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
sharedPref = new SharedPref(this);
if (sharedPref.getNotification()) {
// play vibration
if (sharedPref.getVibration()) {
((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(VIBRATION_TIME);
}
RingtoneManager.getRingtone(this, Uri.parse(sharedPref.getRingtone())).play();
if (remoteMessage.getData().size() > 0) {
Map<String, String> data = remoteMessage.getData();
FcmNotif fcmNotif = new FcmNotif();
fcmNotif.setTitle(data.get("title"));
fcmNotif.setContent(data.get("content"));
fcmNotif.setPost_id(Integer.parseInt(data.get("post_id")));
displayNotificationIntent(fcmNotif);
}
}
}
private void displayNotificationIntent(FcmNotif fcmNotif) {
Intent intent = new Intent(this, ActivitySplash.class);
if (fcmNotif.getPost_id() != -1) {
intent = new Intent(this, ActivityPostDetails.class);
Post post = new Post();
post.title = fcmNotif.getTitle();
post.id = fcmNotif.getPost_id();
boolean from_notif = !ActivityMain.active;
intent.putExtra(ActivityPostDetails.EXTRA_OBJC, post);
intent.putExtra(ActivityPostDetails.EXTRA_NOTIF, from_notif);
}
PendingIntent pendingIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle(fcmNotif.getTitle());
builder.setStyle(new NotificationCompat.BigTextStyle().bigText(fcmNotif.getContent()));
builder.setContentText(fcmNotif.getContent());
builder.setSmallIcon(R.drawable.ic_notification);
builder.setDefaults(Notification.DEFAULT_LIGHTS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
builder.setPriority(Notification.PRIORITY_HIGH);
}
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
int unique_id = (int) System.currentTimeMillis();
notificationManager.notify(unique_id, builder.build());
}
}
yes you can store the your Notification payload in database and create list in fragment and show data from Database and click on any row start activity according to Post ID by getting post id by position
You can save notification message when the notificaton arrived inside
onMessageReceived(RemoteMessage remoteMessage)
method like this
A full example of a notification is like this..
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
/**
* Called when message is received.
*
* #param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
try {
// [START_EXCLUDE]
// There are two types of messages data messages and notification messages. Data messages are handled
// here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
// traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
// is in the foreground. When the app is in the background an automatically generated notification is displayed.
// When the user taps on the notification they are returned to the app. Messages containing both notification
// and data payloads are treated as notification messages. The Firebase console always sends notification
// messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
// [END_EXCLUDE]
// TODO(developer): Handle FCM messages here.
Map<String, String> data = remoteMessage.getData();
String value1 = data.get("key_1");
String value2 = data.get("key_2");
String title=data.get("title");
String msg=data.get("body");
Log.d("Backgraound", value1);
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
sendNotification(title,msg,value1,value2);
}catch (Exception e){
Log.d("Error Line Number",Log.getStackTraceString(e));
}
}
private void sendNotification(String title,String messageBody, String val1,String val2) {
try {
Intent intent = new Intent(this, Notification_activity.class);
//Bundle bundle = getApplicationContext().getExtras();
Bundle basket = new Bundle();
basket.putString("key_1", val1);
basket.putString("key_2", val2);
intent.putExtras(basket);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
String channelId = getString(R.string.default_notification_channel_id);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.spacebar_round)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent)
.setColor( getResources().getColor(R.color.colorPrimary))
.setLargeIcon(BitmapFactory.decodeResource(getApplicationContext().getResources(),
R.mipmap.ic_launcher));
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
"Channel human readable title",
NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}catch (Exception e){
Log.d("Error Line Number",Log.getStackTraceString(e));
}
}
}
Here is my MyFirebaseMessagingService.class
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public MyFirebaseMessagingService() { }
DataBaseUtil dataBaseUtil = null;
String sname;
Intent intent= new Intent();
String orderId;
String strmessage,strmsgtext;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
dataBaseUtil = new DataBaseUtil();
if (remoteMessage.getNotification() != null) {
L.e( "Message Notification Body: " + remoteMessage.getNotification().getBody());
RemoteMessage.Notification fcm = remoteMessage.getNotification();
PojoNotification pojo = new PojoNotification();
pojo.setTitle(fcm.getTitle());
pojo.setContent(fcm.getBody());
Map<String, String> dataMap = remoteMessage.getData();
orderId = dataMap.get("orderId").toString().trim();
sname = dataMap.get("screen_name").toString().trim();
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
pojo.setId(new Random().nextInt(9000));
dataBaseUtil.insertNotification(pojo);
if (SP.getBoolean(SP.LOGIN) ){
showNotification(pojo);
}
else {
}
}else {
L.e( "Message Notification Body: " + "abcv");
}
}
And here is my showNotification method:
void showNotification(PojoNotification pojo) {
intent= new Intent(getApplicationContext(),MainActivity.class);
intent.putExtra("screen_name", sname);
// intent.putExtra(Constance.id,pojo.getId());
PendingIntent pendingIntent = PendingIntent.getActivity(this,0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("default",
"SGrip",
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("YOUR_NOTIFICATION_CHANNEL_DISCRIPTION");
mNotificationManager.createNotificationChannel(channel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), "default")
.setSmallIcon(R.mipmap.ic_launcher) // notification icon
.setContentTitle(pojo.getTitle()) // title for notification
.setContentText(pojo.getContent())// message for notification
// .setSound(alarmSound) // set alarm sound for notification
.setAutoCancel(true); // clear notification after click
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pi);
mNotificationManager.notify(0, mBuilder.build());
}
Here i am getting all the notification background and foreground but the problem i am facing is that when my app is in background the data payload data is not fetching and when my app is foreground all data are getting as required
Here, my launcher activity were i get intent extra
if (getIntent().getExtras() != null) {
for (String key : getIntent().getExtras().keySet()) {
String value = getIntent().getExtras().getString(key);
Log.d(TAG, "Key: " + key + " Value: " + value);
}
}
and here is the notification code server side
{
"registration_ids" : ["cFxiduH5j9I:APA91bEFAYPOR57yDga8urRuhmPuj_CI9h-bIyEwCcQeyFsvnFU_Nh9zkTmQVE7oiwdXchvIIz4DmUW1nqIOslBg_3oV7cWDZBjwb7WFqQ3E4RZ2T2vXCFN6IQ_1pBIfL67pHwthEZA4"],
"notification" : {
"title" : "First Notification",
"text": "Collapsing A",
"sound":"default"
},
"data" : {
"screen_name" : "acc_screen"
}
}
I read many tutorials many stackoverflow Q&A but nothing helping me out. i know the same type of questions are many but am not getting the solution from there so i posted the question.
When your app is in background, intent caught in Launcher activity.
I implemented the same in Kotlin, please refer:
val bundle = intent.extras
if (bundle != null) {
val notificationModel = NotificationModel()
try {
val target = Target()
if (bundle.containsKey("view"))
target.view = bundle.getString("view")
if (bundle.containsKey("circle_id"))
target.circleId = bundle.getString("circle_id")
if (bundle.containsKey("user_id"))
target.userId = bundle.getString("user_id")
if (bundle.containsKey("group_id"))
target.groupId = bundle.getString("group_id")
if (bundle.containsKey("file_id"))
target.fileId = bundle.getString("file_id")
notificationModel.target = target
} catch (ex: JSONException) {
ex.printStackTrace()
}
}
Updated
When your app is in background and click on your notification your default launcher will be launched. To launch your desired activity you need to specify click_action in your notification payload.
$noti = array
(
'icon' => 'new',
'title' => 'title',
'body' => 'new msg',
'click_action' => 'your activity name comes here'
);
And in your android.manifest file
Add the following code where you registered your activity
<activity
android:name="your activity name">
<intent-filter>
<action android:name="your activity name" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
I am developing an Android application in which I would like to receive a Push notification when application state is both in Foreground and Background.
It was working fine before the click_action is added but after adding it does not make the push notification received when the application is background or killed. After some research, I could understand that I will not be able to receive the Push in Background if the FCM is "notification" message type but only "data" message type.
As FCM provides click_action attribute by default and also provides the method getClickAction() to get it in onMessageReceived(), Should I really use click_action in data message ?
The bundle in onMessageReceived
Bundle[{
google.sent_time = 1521177008895,
google.ttl = 3600,
gcm.notification.e = 1,
lastName = Test,
profileUrl = ,
roleId = ,
userId = 140128,
gcm.notification.badge = 1,
gcm.notification.sound =
default,
gcm.notification.title = Someone
try to login with your credentials,
roleName = ,
userName = test,
flag = 0,
from = 612005318045,
type = 0,
gcm.notification.sound2 = simpleSound,
firstName = Test,
gcm.notification.notification_id = 1140,
google.message_id = 0: 1521177008900292 % c05b1316c05b1316,
notification = Someone
try to login with your credentials,
gcm.notification.body = Someone
try to login with your credentials,
gcm.notification.icon = myApp,
notificationId = 2047669,
gcm.notification.notification_type = 1,
gcm.notification.click_action = com.my.push.activities.OPEN_NOTIFICATION_LIST,
gcm.notification.notification_message = TEST MESSAGE,
notificationDate = Fri Mar 16 05: 10: 08 GMT 2018,
collapse_key = com.my.push,
gcm.notification.notification_title = APP
}]
The code snippet of the way it is handled in onMessageReceived
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
......
......
showNotification(remoteMessage);
}
public void showNotification(RemoteMessage remoteMessage) {
try {
Map<String, String> response = remoteMessage.getData();
Intent intent = prepareIntent(remoteMessage);
PendingIntent pIntent = PendingIntent.getActivity(this, 0,
intent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "D4E_ANDROID")
.setContentTitle("New Notification")
.setContentText(response.get("notification"))
.setSmallIcon(R.drawable.d4e_logo)
.setContentIntent(pIntent)
.setAutoCancel(true)
.addAction(R.drawable.view_icon, "View", pIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(Integer.parseInt(response.get("notificationId")), builder.build());
} catch (Exception exception) {
Log.e("OnREC", exception.toString());
}
}
public Intent prepareIntent(RemoteMessage remoteMessage) {
Map<String, String> response = remoteMessage.getData();
Intent intent;
boolean isAppInBackground;
if (SessionContext.isLoggedIn()) {
isAppInBackground = SessionHelper.initializeSessionHelper().isAppInBackground(this);
Log.e("LOGGGGG", isAppInBackground + "");
if (isAppInBackground) {
intent = new Intent(this, SplashScreen.class);
} else {
intent = new Intent(remoteMessage.getNotification().getClickAction());
}
}
} else {
intent = new Intent(this, LoginActivity.class);
}
return intent;
}
Please anyone guide me to find the solution.
if you can receive FCM notification sent through console, then potentially something is wrong with build the notification. one suspect is that you are not using "icon" field.
If you can debug android device, set breakpoint here and see if you get error or missed some resource.
https://github.com/evollu/react-native-fcm/blob/master/android/src/main/java/com/evollu/react/fcm/SendNotificationTask.java#L46
hello i have android application and i used Firebase notification and its working good ,, now i need to receive silent push without alert or anything ,,, i tried some idea and its working when app is running but when app in background or terminated its not working ! if anyone have idea to sole this issue please tell me :) this is my code
public class MyFirebaseMessagingService extends FirebaseMessagingService {
Boolean isSilent;
String Silent = "";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
try {
Bundle bundle = new Bundle();
for (Map.Entry<String, String> entry : remoteMessage.getData().entrySet()) {
bundle.putString(entry.getKey(), entry.getValue());
Log.d(entry.getKey(), entry.getValue());
}
// remoteMessage.getData().get("screen_id")
if (remoteMessage.getData().size() > 0) {
sendNotificationData(bundle.getString("data_title"), bundle.getString("data_body"), bundle.getString("screen_id"));
} else if (remoteMessage.getNotification() != null) {
sendNotification(remoteMessage.getNotification(), bundle.getString("screen_id"));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void sendNotification(RemoteMessage.Notification notificationR, String screenId) {
NotificationManager nManager = (NotificationManager) this.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
Intent intentNotification = new Intent(this, MainActivity.class);
intentNotification.putExtra("screen_id", screenId);
Log.v("sendNotification ", " >>>>>####>>>>>>>> " + screenId);
// finish previous activity
if (!Silent.equals("yes")) {
intentNotification.addFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 50, intentNotification, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this.getApplicationContext())
.setContentTitle(notificationR.getTitle())
.setContentText(notificationR.getBody())
.setSmallIcon(getNotificationIcon())
.setLargeIcon(icon(getApplicationContext()))
.setLights(Color.LTGRAY, 1000, 1000)
.setAutoCancel(true)
.setTicker(notificationR.getTitle())
.setContentIntent(pendingIntent)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
Notification notification = notificationBuilder.build();
// '|' Binary OR Operator copies a bit if it exists in either operand. to ensure no conflict on the flags
notification.flags = notification.flags | Notification.FLAG_SHOW_LIGHTS;
nManager.notify((int) SystemClock.currentThreadTimeMillis(), notification);
}
}
private void sendNotificationData(String dataTitle, String dataBody, String screenId) {
NotificationManager nManager = (NotificationManager) this.getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
Intent intentNotification = new Intent(this, MainActivity.class);
intentNotification.putExtra("screen_id", screenId);
if (!Silent.equals("yes")) {
intentNotification.addFlags(android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 50, intentNotification, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this.getApplicationContext())
.setContentTitle(dataTitle)
.setContentText(dataBody)
.setSmallIcon(getNotificationIcon())
.setLargeIcon(icon(getApplicationContext()))
.setLights(Color.LTGRAY, 1000, 1000)
.setAutoCancel(true)
.setTicker(dataTitle)
.setContentIntent(pendingIntent)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
Notification notification = notificationBuilder.build();
// '|' Binary OR Operator copies a bit if it exists in either operand. to ensure no conflict on the flags
notification.flags = notification.flags | Notification.FLAG_SHOW_LIGHTS;
nManager.notify((int) SystemClock.currentThreadTimeMillis(), notification);
}
#Override
public boolean zzE(Intent intent) {
isSilent = intent.hasExtra("silent");
if (isSilent) {
Silent = "yes";
}
return super.zzE(intent);
}
when app is running this code is working but at background or terminated its not working !!
When your app is in Background firbase notification message received on 'System tray' that's why FirebaseMessagingService.onMessageReceived not called.
When your app is in the background, Android directs notification messages to the system tray. A user tap on the notification opens the app launcher by default.
Try to sent data payload that will call onMessageReceived. and your code will
work
For data message....
Get firebase token from FirebaseInstanceIdService and sent it to app server.
Google have very good documentation to sent it Here
You can sent it using php also.
Then on onMessageReceived
if (remoteMessage.getData().size() > 0) {
String title = remoteMessage.getData().get("title");
String body = remoteMessage.getData().get("body");
String screen = remoteMessage.getData().get("screen");
sendNotification(title, body, screen );}
For Server side php implementation
<?php
$path_to_fcm = "https://fcm.googleapis.com/fcm/send";
$headers = array(
'Authorization:key='YOUR_SERVER_KEY,
'Content-Type:application/json'
);
$reg_id_array = array
(
'token1',
'token2'
)
$mesg = array
(
'title'=>$_POST['title'],
'body'=> $_POST['message'],
'url'=>$_POST['Screen'],
);
$fields = array("registration_ids"=>$reg_id_array, 'data'=>$mesg);
$payload = json_encode($fields);
$curl_session = curl_init();
curl_setopt($curl_session, CURLOPT_URL, $path_to_fcm);
curl_setopt($curl_session, CURLOPT_POST, true);
curl_setopt($curl_session, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl_session, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl_session, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl_session, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
curl_setopt($curl_session, CURLOPT_POSTFIELDS, $payload);
$Qresult = curl_exec($curl_session);
$httpcode = curl_getinfo($curl_session , CURLINFO_HTTP_CODE);
curl_close($curl_session);
if ($httpcode==200) {
echo "Success";
}
?>
Sorry bad English
A Notification contains 2 thigs:
the notification itself and
extra data.
You seem to have data in your code because of values such as screen_id, data_title``etc. It actually looks you are reading everything from thedata` part, I will leave the docs here just in case. In the first table in that page explains where each notification is handled.
Since you use data, all notifications will be manged in onMessageReceived, so the only think I can think of is you terminated the app from Android Studio (through the Stop button).
Doing so, the App terminates, and also does background Firebase instance. All processes exit. So try closing it from the mobile, and report if it worked.
Good luck.
There should be clear implementation of how to work with Firebase notification and data. I read many answers but can't seem to make it work. here are my steps:
1.) I am passing notification and data to android in PHP and it seems to be fine:
$msg = array
(
"body" => $body,
"title" => $title,
"sound" => "mySound"
);
$data = array
(
"user_id" => $res_id,
"date" => $date,
"hal_id" => $hal_id,
"M_view" => $M_view
);
$fields = array
(
'registration_ids' => $registrationIds,
'notification' => $msg,
'data' => $data
);
$headers = array
(
'Authorization: key='.API_ACCESS_KEY,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
curl_close( $ch );
2.) when notification and data is received in Android it shows notification. When I click on this notification it opens app. But I can not figure out the way to handle the data when the app is opened. There are couple differences when app is in foreground and backround. The code that I have now is the following:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
String user_id = "0";
String date = "0";
String cal_id = "0";
String M_view = "0";
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
user_id = remoteMessage.getData().get("user_id");
date = remoteMessage.getData().get("date");
hal_id = remoteMessage.getData().get("hal_id");
M_view = remoteMessage.getData().get("M_view");
}
//Calling method to generate notification
sendNotification(remoteMessage.getNotification().getBody(), user_id, date, hal_id, M_view);
}
private void sendNotification(String messageBody, String user_id, String date, String hal_id, String M_view) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("fcm_notification", "Y");
intent.putExtra("user_id", user_id);
intent.putExtra("date", date);
intent.putExtra("hal_id", hal_id);
intent.putExtra("M_view", M_view);
int uniqueInt = (int) (System.currentTimeMillis() & 0xff);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), uniqueInt, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setSmallIcon(R.drawable.ic_launcher)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}}
3.) When I use the code above and when I click on notification all it does it opens the app if in background. If app in foreground then on notification click it simply dismisses notification. However, I want to receive data and open specific Activity in both scenarios (background and foreground). I have in MainActivity the following code, but I am not able to get data. fcm_notification, date, hal_id returns null.
public class MainActivity extends Activity {
UserFunctions userFunctions;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
Intent intent_o = getIntent();
}
#Override
protected void onResume() {
super.onResume();
userFunctions = new UserFunctions();
if(userFunctions.isUserLoggedIn(getApplicationContext())){
Intent intent_o = getIntent();
String fcm_notification = intent_o.getStringExtra("fcm_notification") ;
String user_id = intent_o.getStringExtra("user_id");
String date = intent_o.getStringExtra("date");
String hal_id = intent_o.getStringExtra("hal_id");
String M_view = intent_o.getStringExtra("M_view");
Intent intent = new Intent(this, JobList.class);
// THIS RETURNS NULL, user_id = null
System.out.print("FCM" + user_id);
startActivity(intent);
finish();
}else{
// user is not logged in show login screen
Intent login = new Intent(this, LoginActivity.class);
startActivity(login);
// Closing dashboard screen
finish();
}
}}
IF anyone can direct or advice how can I retrieve data in MainActivity.java from Firebase in either scenario (foreground or background) that would be fantastic.
So first off, I'll put in the detail mentioned in the Handling Messages docs.
In the summary under the Both row, it shows that when the app is on foreground, the payload will be handled in your onMessageReceived().
In order to open the activity from onMessageReceived(), you should check if the data you need is in the payload, if it does, call your specific activity then pass all the other details you need via intent.
Now if the app is in background, it is mentioned in the docs that the notification is received by the Android system tray and that the data payload can be retrieved from the extras of the intent.
Just adding in the details from my answer here which pretty much just gives the docs statement and a link to a sample:
Handle notification messages in a backgrounded app
When your app is in the background, Android directs notification messages to the system tray. A user tap on the notification opens the app launcher by default.
This includes messages that contain both notification and data payload (and all messages sent from the Notifications console). In these cases, the notification is delivered to the device's system tray, and the data payload is delivered in the extras of the intent of your launcher Activity.
I think this answer by #ArthurThompson explains it very well:
When you send a notification message with a data payload (notification and data) and the app is in the background you can retrieve the data from the extras of the intent that is launched as a result of the user tapping on the notification.
From the FCM sample which launches the MainActivity when the notification is tapped:
if (getIntent().getExtras() != null) {
for (String key : getIntent().getExtras().keySet()) {
String value = getIntent().getExtras().getString(key);
Log.d(TAG, "Key: " + key + " Value: " + value);
}
}
After trying all the answers and blogs came up with solution. if anyone needs please use this video as reference
https://www.youtube.com/watch?v=hi8IPLNq59o
IN ADDITION to the video to add intents do in MyFirebaseMessagingService:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
String user_id = "0";
String date = "0";
String hal_id = "0";
String M_view = "0";
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
user_id = remoteMessage.getData().get("user_id");
date = remoteMessage.getData().get("date");
cal_id = remoteMessage.getData().get("hal_id");
M_view = remoteMessage.getData().get("M_view");
}
String click_action = remoteMessage.getNotification().getClickAction();
//Calling method to generate notification
sendNotification(remoteMessage.getNotification().getBody(), remoteMessage.getNotification().getTitle(), user_id, date, hal_id, M_view, click_action);
}
private void sendNotification(String messageBody, String messageTitle, String user_id, String date, String hal_id, String M_view, String click_action) {
Intent intent = new Intent(click_action);
intent.putExtra("user_id", user_id);
intent.putExtra("date", date);
intent.putExtra("hal_id", hal_id);
intent.putExtra("M_view", M_view);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}}
and in new NotificationReceive activity in onCreate or onResume add this
notification_Y_N = (TextView) findViewById(R.id.notification_Y_N);
user_id_text = (TextView) findViewById(R.id.user_id_text);
Intent intent_o = getIntent();
String user_id = intent_o.getStringExtra("user_id");
String date = intent_o.getStringExtra("date");
String hal_id = intent_o.getStringExtra("hal_id");
String M_view = intent_o.getStringExtra("M_view");
notification_Y_N.setText(date);
user_id_text.setText(hal_id);
To invoke the onMessageReceived() method you will need to use another method to send notifications (like creating a Web API to send notifications). Then using it,
remove the notification payload from your FCM messages in order to have the data payload delivered to the onMessageReceived() method.
When your app is in the background, data payload is delivered to the onMessageReceived method only if there is no notification payload.
In case both payloads exist then system automatically handles the
notification part (system tray) and your app gets the data payload in
the extras of the intent of launcher Activity (after the user tap on
the notification).
For more info please refer to the following links:
Why is this happening? How to? How to handle push notifications?
Original answer by kws. Give him an upvote.
You don't need to implement sendNotification and onMessageReceived yourself.
When sending:
$data = array
(
"user_id" => $res_id
//whatever fields you want to include
);
$msg = array
(
"body" => $body,
"title" => $title,
"data" => $data
// more fields
);
android side (on your MainACtivity:
private void handleIntent(Intent intent) {
String user_id= intent.getStringExtra("user_id");
if(user_id!= null)
Log.d(TAG, user_id);
}
and of course:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handleIntent(getIntent());
}
whatever fields you put in data will be sent to your intent extra.
firstly, if you have data object and notification object in response . then ask the backend developer to remove notification object.
i hope my own class help .
public class MyFirebaseService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
Log.d(TAG, "Message data payload:id " + remoteMessage.getData().get("mode_id"));
sendNotification(remoteMessage.getData().get("body"),
remoteMessage.getData().get("mode_id"), remoteMessage.getData().get("click_action"));
}
}
private void sendNotification(String messageBody, String id, String clickAction) {
Intent intent = new Intent(clickAction);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntentWithParentStack(intent);
intent.putExtra("id", id);
intent.putExtra("body", messageBody);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "111")
.setSmallIcon(R.drawable.venus_logo)
.setContentText(messageBody)
.setAutoCancel(true)
.setVibrate(new long[]{1000, 1000, 1000, 1000, 1000})
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(pendingIntent)
.setLights(Color.GREEN, 3000, 3000);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel("111", "NOTIFICATION_CHANNEL_NAME", importance);
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.enableVibration(true);
notificationChannel.setShowBadge(false);
notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
assert notificationManager != null;
notificationBuilder.setChannelId("111");
notificationManager.createNotificationChannel(notificationChannel);
notificationManager.notify(0, notificationBuilder.build());
} else {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(0, notificationBuilder.build());
}
}
}
then add this to your manifest file .
<service
android:name=".data.services.MyFirebaseService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<activity
android:name=".ui.notifications.NotificationsDetailsActivity"
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:parentActivityName=".ui.home.HomeActivity"
android:taskAffinity="">
<intent-filter>
<action android:name="co.example.yourApp.ui.notifications_TARGET_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Firebase documentation has a great table to explain how it works
https://firebase.google.com/docs/cloud-messaging/android/receive#handling_messages
So if you have both data and notification and app is in a foreground when your receive it then you should create a notification by yourself in your service which extends FirebaseMessagingService (in onMessageReceived method)
In other case (app is in background) you can get your data from intent.extras of Activity, a notification will be created by a system to open main activity of the app