I have a problem with my app based on AWS. When I test the following function in Amazon lambda, everything works (I get the push notification on my phone):
console.log("Loading kupa function");
var AWS = require("aws-sdk");
exports.handler = function(event, context) {
var eventText = JSON.stringify(event, null, 2);
console.log("Received event:", eventText);
var sns = new AWS.SNS();
var params = {
Message: eventText,
Subject: "Test SNS From Lambda",
TopicArn: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
};
sns.publish(params, context.done);
context.succeed("kupa sukces");
};
However, once I use the following method on my phone I get the "kupa sukces" log into my Android Studio but I don't get the notification on the phone. Furthermore, the "Test" on Lambda does not work anymore as wel...
Here is the code:
String lambdaRequest = "{\n\"kupa\" : \"" + true + "\"\n}";
asyncTask.delegate = wysylaczKupy.this;
asyncTask.friendFunction("friendsRequest",lambdaRequest);
}
the friendFunction is here:
public static void friendFunction(String funName, String requestContent) {
final String functionName = funName;
final String requestPayload = requestContent;
new AsyncTask<Void, Void, InvokeResult>() {
#Override
protected InvokeResult doInBackground(Void... params) {
try {
final ByteBuffer payload =
ENCODER.encode(CharBuffer.wrap(requestPayload));
final InvokeRequest invokeRequest =
new InvokeRequest()
.withFunctionName(functionName)
.withInvocationType(InvocationType.RequestResponse)
.withPayload(payload);
final InvokeResult invokeResult =
AWSMobileClient
.defaultMobileClient()
.getCloudFunctionClient()
.invoke(invokeRequest);
return invokeResult;
} catch (final Exception e) {
Log.e("LAMBDA", "AWS Lambda invocation failed : " + e.getMessage(), e);
final InvokeResult result = new InvokeResult();
result.setStatusCode(500);
result.setFunctionError(e.getMessage());
return result;
}
}
}
How can I fix this?
Thank you in advance,
Jan
Jan,
The Lambda function for publishing to an SNS Topic wasn't quite right. I modified your function and provided a default json value for testing. Just put your TopicARN in and try it out. Once you have tested using the Lambda console, then try the Android code, which I did not try.
Note that when sending a JSON payload to an SNS Topic, a default value is required. The default value is used when you don't specify a protocol specific message. For example, you are publishing to an SNS Topic with Android GCM endpoints and since your JSON payload does not contain "GCM" then all endpoints will receive your default message that you provided.
I'm not sure what you were doing with "{\n\"kupa\" : \"" + true + "\"\n}" but I'm guessing the "kupa": "true" is intended to the the data key/value for the app to handle? If so, you'll need to lookup a proper GCM payload to send both a message and data.
//Pass in the following json for testing: { "default":"some message", "kupa": "true"}
console.log("Loading kupa function");
var AWS = require("aws-sdk");
exports.handler = function(event, context, callback) {
var eventText = JSON.stringify(event, null, 2);
console.log("Received event:", eventText);
var sns = new AWS.SNS();
var params = {
Message: eventText,
MessageStructure: "json",
Subject: "Test SNS From Lambda",
TopicArn: "arn:aws:sns:us-west-2:xxxxxxxxxx:test"
};
sns.publish(params, function (err, data) {
if(err){
callback(err, null); //failed
}
callback(null, "kupa sukces"); //success
});
};
Related
I'm making chat application trying to get push notification when new message received to user from another when app is in background using send notifications between Android devices using Firebase Database, Cloud Messaging and Node.js.
I'm following this blog.Here's
[https://firebase.googleblog.com/2016/08/sending-notifications-between-android.html]
and below is my code which I tried.
#Override
public void onClick(View view) {
if (view.getId() == R.id.btnSend) {
String content = editWriteMessage.getText().toString().trim();
if (content.length() > 0) {
editWriteMessage.setText("");
Message newMessage = new Message();
newMessage.text = content;
newMessage.idSender = StaticConfig.UID;
newMessage.idReceiver = roomId;
newMessage.timestamp = System.currentTimeMillis();
FirebaseDatabase.getInstance().getReference().child("message/" + roomId).push().setValue(newMessage);
sendNotificationToUser(newMessage.idReceiver,newMessage.text);
}
}
}
public void sendNotificationToUser(String user, String message) {
Map notification = new HashMap<>();
notification.put("username", user);
notification.put("message", message);
FirebaseDatabase.getInstance().getReference().child("notificationRequests").push().setValue(notification);
}
By using above codes the username and message is getting saved in real time database in notificationRequests.
And I really don't have idea that how can the push notification is received by this line of code.
FirebaseMessaging.getInstance().subscribeToTopic("user_"+username);
And the most important where do i need to put the above code to make it work.
and also I have created the bucket to host my node.js file.
thanks in advance.
EDIT: I misunderstood your problem. Make sure that firebase messaging service is in your manifest.xml file.
Original:
Use the functions.database.ref().onCreate() method. Inside the ref() parameters put the path to your notification requests.
Here's some base code in TypeScript.
export const notificationListener = functions.database
.ref('/NotificationRequests/{notification}').onCreate((snapshot, context) =>
{
try {
admin.initializeApp();
} catch (e) {
}
//Code to send notification here
return admin.database().ref('/NotificationRequests/' + context.params.notification)
}
)
The information you need for the notification is located under snapshot.child('your path here').
See why and how this works
Is there any way to send a push notification from server when a user complete a task? For example: A todo app will notify on that date with push notification. I want to use firebase and firestore for storing user tokens.
Alarm manager can be a solution that I have found but I don't wanna use it.
Yes, you can use scheduler to send notification from server to your app:
You may follow my working code:
Emplement IJob:
public class SendNotificationViaFcm: IJob
{
public void Execute(IJobExecutionContext context)
{
bool isNotificationSent=false;
try
{
var taskToSendNotification = FirebaseCloudMessaging.SendMessage();
Task.WaitAll(taskToSendNotification);
isNotificationSent = taskToSendNotification.Result;
}
catch (Exception exception)
when (
exception is ObjectDisposedException || exception is ArgumentNullException ||
exception is AggregateException)
{
}
catch (Exception exception) when (exception is InvalidOperationException)
{
}
catch (Exception exception)
{
// ignored
}
}
}
Call FCM Api from your server:
public class FirebaseCloudMessaging
{
private static readonly Uri FcmUri = new Uri(
uriString: #"https://fcm.googleapis.com",
uriKind: UriKind.Absolute);
private const string FcmApiKey = "Your Legacy Server Key";
public static async Task<bool> SendMessage()
{
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = FcmUri;
httpClient.DefaultRequestHeaders.Clear();
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization",
"key=" + FcmApiKey);
var response = await httpClient.PostAsJsonAsync(#"/fcm/send", new
{
to = "/topics/global",
priority = "high",
data = new
{
title = "Warning",
message = "Please start app to track movemoent!"
}
//to = "/topics/global",
//priority = "high",
//notification = new
//{
// title = "Warning!",
// body = "Please start app to track movemoent!"
//}
});
Debug.Write(response.Content.ReadAsStringAsync());
var ck = response.IsSuccessStatusCode;
return response.IsSuccessStatusCode;
}
}
}
Implement schedular for your time interval:
public class Scheduler
{
public static void Start()
{
try
{
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Start();
// scheduler.Shutdown();
var sentCloudNotification = JobBuilder.Create<SendNotificationViaFcm>().Build();
var cloudNotificationTrigger = TriggerBuilder.Create().WithSimpleSchedule(x => x.WithIntervalInMinutes(1).RepeatForever()).Build();
scheduler.ScheduleJob(sentCloudNotification, cloudNotificationTrigger);
}
catch (SchedulerException exception)
{
Debug.Write(exception.Message);
}
catch (Exception exception)
{
Debug.Write(exception.Message);
}
}
}
Finally Run in from your Global.asax.cs
protected void Application_Start()
{
Scheduler.Start();
}
It sounds like you're looking for a tool that allows you to schedule transactional notifications. What sort of server technology are you using?
From a high level you could do something like this:
1) user adds a task in the Android application
2) android application sends request to server to save the task
3) you have some code that runs in some sort of on task save callback that schedules a block of code to run in the future using crontab, celery or something similar.
4) the block of code that runs in the future is an api call to twilio to send a push notification
relevant links: https://www.twilio.com, https://firebase.google.com/docs/cloud-messaging/, http://www.celeryproject.org/, https://en.wikipedia.org/wiki/Cron
i'm developing an android app and i followed this link to use google push notification
my problem is that the first time that app starts, push notification work's fine but as I restart my app, push notification stops working and I cant receive notifications.
here is my code:
[Service(Exported = false)]
class RegistrationIntentService : IntentService
{
static object locker = new object();
public RegistrationIntentService() : base("RegistrationIntentService") { }
protected override void OnHandleIntent(Intent intent)
{
try
{
Log.Info("RegistrationIntentService", "Calling InstanceID.GetToken");
lock (locker)
{
var instanceID = InstanceID.GetInstance(this);
var token = instanceID.GetToken(
"my_id", GoogleCloudMessaging.InstanceIdScope, null);
Log.Info("RegistrationIntentService", "GCM Registration Token: " + token);
SendRegistrationToAppServer(token);
Subscribe(token);
}
}
catch (Exception e)
{
Log.Debug("RegistrationIntentService", "Failed to get a registration token");
return;
}
}
void SendRegistrationToAppServer(string token)
{
// some code
}
void Subscribe(string token)
{
var pubSub = GcmPubSub.GetInstance(this);
pubSub.Subscribe(token, "/topics/global", null);
}
}
[Service(Exported = false), IntentFilter(new[] { "com.google.android.c2dm.intent.RECEIVE" })]
public class MyGcmListenerService : GcmListenerService
{
public override void OnMessageReceived(string from, Bundle data)
{
Log.Debug("MyGcmListenerService", "From: " + from);
Log.Debug("MyGcmListenerService", "Message: " + message);
}
}
[Service(Exported = false), IntentFilter(new[] { "com.google.android.gms.iid.InstanceID" })]
class MyInstanceIDListenerService : InstanceIDListenerService
{
public override void OnTokenRefresh()
{
var intent = new Intent(this, typeof(RegistrationIntentService));
StartService(intent);
}
}
and i send notification with this method
public static void SendNotification(string MESSAGE, string token)
{
var jGcmData = new JObject();
var jData = new JObject();
jData.Add("message", MESSAGE);
jGcmData.Add("to", token);
jGcmData.Add("data", jData);
var url = new Uri("https://gcm-http.googleapis.com/gcm/send");
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation(
"Authorization", "key=" + API_KEY);
System.Threading.Tasks.Task.WaitAll(client.PostAsync(url,
new StringContent(jGcmData.ToString(), Encoding.Default, "application/json"))
.ContinueWith(response =>
{
Console.WriteLine(response);
Console.WriteLine("Message sent: check the client device notification tray.");
}));
}
}
catch (Exception e)
{
Console.WriteLine("Unable to send GCM message:");
Console.Error.WriteLine(e.StackTrace);
}
}
do you have any idea?
Is this in the emulator? I had this issue with the emulator and fixed it by turning off the option to preserve application data/cache between deploys. In Visualstudio it's Tools->Options-Xamarin->Android Options. Now I get a new token on each deploy and it always works.
Why this happens I haven't figured out. Maybe it's a security feature that a different build of the app cannot use the same taken?
From the official documentation of Xamarin:
"If you force-close the app, FCM will stop delivering notifications. Android prevents background service broadcasts from inadvertently or unnecessarily launching components of stopped applications. (For more information about this behavior, see Launch controls on stopped applications.) For this reason, it is necessary to manually uninstall the app each time you run it and stop it from a debug session – this forces FCM to generate a new token so that messages will continue to be received."
https://learn.microsoft.com/en-us/xamarin/android/data-cloud/google-messaging/remote-notifications-with-fcm?tabs=windows
I am trying to learn to use azure mobile app, but I am having serious problems in using the NotificationHub. I have an Imagine subscription to Azure. I creating an android mobile app with azure backend. I have created a notification hub associated to the azure mobile app on the azure portal.
To register the app on the notification hub I used the code in this tutorial:
https://learn.microsoft.com/en-gb/azure/notification-hubs/notification-hubs-android-push-notification-google-fcm-get-started
The users are authenticated on the azure backend previuosly by using their google account, microsoft account or facebook account. New users are inserted into the table Users by the following node js code written for the table script Users.js. I want a push notification to Welcome the new User.
var azureMobileApps = require('azure-mobile-apps');
var logger = require('azure-mobile-apps/src/logger');
var table = azureMobileApps.table();
table.access = 'authenticated';
/**
* Adds the email address from the claims to the context item - used for
* insert operations
* #param {Context} context the operation context
* #returns {Promise} context execution Promise
*/
function addEmailToContext(context) {
/*
* Getting claim fields
*/
return context.user.getIdentity().then((data) => {
if( data.microsoftaccount != undefined){
context.item.email = data.microsoftaccount.claims.emailaddress;
context.item.name = data.microsoftaccount.claims.givenname;
context.item.surname = data.microsoftaccount.claims.surname;
}
if( data.google != undefined){
context.item.email = data.google.claims.emailaddress;
context.item.name = data.google.claims.givenname;
context.item.surname = data.google.claims.surname;
context.item.picture_url = data.google.claims.picture;
}
if( data.facebook != undefined){
context.item.email = data.facebook.claims.emailaddress;
context.item.name = data.facebook.claims.givenname;
context.item.surname = data.facebook.claims.surname;
}
logger.info('[tables/Users.js] --> NEW USER REGISTERED:'
+'\n\t Name:'+context.item.name
+'\n\t Surname:'+context.item.surname
+'\n\t Email:'+context.item.email);
// Execute the insert. The insert returns the results as a Promise,
// Do the push as a post-execute action within the promise flow.
return context.execute()
.then(function (results) {
// Only do the push if configured
if (context.push) {
// Mobile Apps adds a user tag when registering for push notifications
// Define the GCM payload.
var payload = {
"data": {
"message": 'Welcome '+context.item.username
}
};
context.push.gcm.send(context.user.id, payload, function (error) {
if (error) {
logger.error('Error while sending push notification: ', error);
} else {
logger.info('Push notification sent successfully!');
}
});
}
// Don't forget to return the results from the context.execute()
return results;
})
.catch(function (error) {
logger.error('Error while running context.execute: ', error);
});
});
}
// CREATE - add or overwrite the authenticated user
table.insert(addEmailToContext);
module.exports = table;
According to "How to: Send push notifications to an authenticated user using tags" in the tutorial on How to use the Azure Mobile Apps Node.js SDK
"When an authenticated user registers for push notifications, a user ID tag is automatically added to the registration. "
So in the Users.js, as suggested in this tutorial I wrote the following code to send the push notification to the user.
context.push.gcm.send(context.user.id, payload, function (error) {
if (error) {
logger.error('Error while sending push notification: ', error);
} else {
logger.info('Push notification sent successfully!');
}
});
With this code the push notification results to be sent successfully, but the device doesn't receive any notifications. If I use null instead of context.user.id then all devices receive the push notification correctly:
context.push.gcm.send(null, payload, function (error) {
if (error) {
logger.error('Error while sending push notification: ', error);
} else {
logger.info('Push notification sent successfully!');
}
});
I also tried to invoke the following custom API to create tag when the user is registered to the hub. The invoked API is the following:
var logger = require('azure-mobile-apps/src/logger');
exports.post = function(req, res) {
logger.info('[api/registerTag.js] --> Invoked');
// Get the notification hub used by the mobile app.
var push = req.azureMobile.push,
installationId = req.get('X-ZUMO-INSTALLATION-ID'),
tags = req.body.tag.toString();
// Define an update tags operation.
var updateOperation = [{
"op": "add",
"path": "/tags",
"value": tags
}];
// Update the installation to add the new tags.
push.patchInstallation(installationId, updateOperation, function(error) {
if(error){
logger.error('[api/registerTag.js] --> An error occurred while adding'
+'the following tags: \n\t'+tags, error);
res.status(error.statusCode).send(error.detail);
} else {
logger.info('[api/registerTag.js] --> The following tags have been added'
+'to the Notification Hub: \n\t'+tags, error);
res.status(200).send(tags);
}
});
};
On the console it is printed that the tag has been added successfully. But if I then modify the Users.js code like this:
...
// Only do the push if configured
if (context.push) {
// Mobile Apps adds a user tag when registering for push notifications
var userTag = '_UserId:' + context.user.id;
logger.info("TAG "+userTag);
// Define the GCM payload.
var payload = {
"data": {
"message": 'Welcome '+context.item.username
}
};
context.push.gcm.send(userTag, payload, function (error) {
if (error) {
logger.error('Error while sending push notification: ', error);
} else {
logger.info('Push notification sent successfully!');
}
});
}
...
again nothing is received. I have also tried whitelisting tags or adding them automatically using the Push section of the mobile app like shown in the image:
IMAGE LINK: i.stack.imgur.com/KBvQI.png
But the problem is still there. Hope someone can help me. Thanks.
After several times of testing, I succeeded in reproducing your issue and got the same problem. To achieve your requirement I did some modification in Android client-end:
1, Cache authentication user in the MainActivity class. Following is my code snippet. For more details you can refer here.
public static final String SHAREDPREFFILE = "temp";
public static final String USERIDPREF = "uid";
public static final String TOKENPREF = "tkn";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
// Create the Mobile Service Client instance, using the provided Mobile Service URL and key
mClient = new MobileServiceClient(
"https://yourwebsitename.azurewebsites.net",
this).withFilter(new ProgressFilter());
// Extend timeout from default of 10s to 20s
mClient.setAndroidHttpClientFactory(new OkHttpClientFactory() {
#Override
public OkHttpClient createOkHttpClient() {
OkHttpClient client = new OkHttpClient();
client.setReadTimeout(20, TimeUnit.SECONDS);
client.setWriteTimeout(20, TimeUnit.SECONDS);
return client;
}
});
authenticate();
} catch (MalformedURLException e) {
createAndShowDialog(new Exception("There was an error creating the Mobile Service. Verify the URL"), "Error");
} catch (Exception e){
createAndShowDialog(e, "Error");
}
}
private void authenticate() {
// We first try to load a token cache if one exists.
if (loadUserTokenCache(mClient)) {
createTable();
register();
}
// If we failed to load a token cache, login and create a token cache
else {
// Login using the Google provider.
ListenableFuture<MobileServiceUser> mLogin = mClient.login(MobileServiceAuthenticationProvider.Google);
Futures.addCallback(mLogin, new FutureCallback<MobileServiceUser>() {
#Override
public void onFailure(Throwable exc) {
createAndShowDialog("You must log in. Login Required", "Error");
}
#Override
public void onSuccess(MobileServiceUser user) {
createAndShowDialog(String.format("You are now logged in - %1$2s", user.getUserId()), "Success");
cacheUserToken(mClient.getCurrentUser());
createTable();
register();
}
});
}
}
private void cacheUserToken(MobileServiceUser user) {
SharedPreferences prefs = getSharedPreferences(SHAREDPREFFILE, Context.MODE_PRIVATE);
Editor editor = prefs.edit();
editor.putString(USERIDPREF, user.getUserId());
editor.putString(TOKENPREF, user.getAuthenticationToken());
editor.commit();
}
private void register() {
NotificationsManager.handleNotifications(this, NotificationSettings.SenderId, MyHandler.class);
registerWithNotificationHubs();
}
2, In RegistrationIntentService class replace regID = hub.register(FCM_token).getRegistrationId(); with the following code:
regID = hub.register(FCM_token, prefs.getString("uid", "")).getRegistrationId();
3, Make sure add the line below to the first line within onHandleIntent method.
SharedPreferences prefs = getSharedPreferences("temp", Context.MODE_PRIVATE);
I wonder if it's possible to send push notifications to android mobile devices whenever Firebase gets added a new child on specific entity.
For example, let's say there's an entity on Firebase called Tasks. Whenever a new task is added to that firebase collection the "child_added" event is fired and then, in some way, a push notification is sent to a mobile client.
The trigger is the child_added event. However, I'm not sure if is feasible sending push notification right from Firebase events.
You can make a very simple node.js server or a java servlet (based on your language preferences) then using firebase server sdk you can add childEventListener. When value changes you can use FCM to send push notifications using http protocol. I am using this in my app and it is very feasable and reliable.
Note: If you are using this flow for an android app then using java server sdk will be beneficial as it is almost similar to what you have on android.
EDIT: After getting some spotlight on this answer I thought to share some more info regarding same.
//example node.js server as seen on this official firebase blog
var firebase = require('firebase');
var request = require('request');
var API_KEY = "..."; // Your Firebase Cloud Server API key
firebase.initializeApp({
serviceAccount: ".json",
databaseURL: "https://.firebaseio.com/"
});
ref = firebase.database().ref();
function listenForNotificationRequests() {
var requests = ref.child('notificationRequests');
ref.on('child_added', function(requestSnapshot) {
var request = requestSnapshot.val();
sendNotificationToUser(
request.username,
request.message,
function() {
request.ref().remove();
}
);
}, function(error) {
console.error(error);
});
};
function sendNotificationToUser(username, message, onSuccess) {
request({
url: 'https://fcm.googleapis.com/fcm/send',
method: 'POST',
headers: {
'Content-Type' :' application/json',
'Authorization': 'key='+API_KEY
},
body: JSON.stringify({
notification: {
title: message
},
to : '/topics/user_'+username
})
}, function(error, response, body) {
if (error) { console.error(error); }
else if (response.statusCode >= 400) {
console.error('HTTP Error: '+response.statusCode+' - '+response.statusMessage);
}
else {
onSuccess();
}
});
}
// start listening
listenForNotificationRequests();
//example test java servlet which I made just to demonstrate this use case
#WebServlet("/TestServlet")
public class MainServlet extends HttpServlet {
* #see HttpServlet#HttpServlet()
*/
public MainServlet() {
super();
}
/**
* #see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Get context and then relative path to saved json config file from
// firebase
ServletContext context = getServletContext();
String fullPath = context.getRealPath(FILE_PATH_FOR_JSON_SERVER_AUTH);
// Check if we actually got a file from above path
if (fullPath != null) {
} else {
}
// Setup connection to firebase database here
FirebaseOptions options = new FirebaseOptions.Builder().setServiceAccount(new FileInputStream(fullPath))
.setDatabaseUrl(FIREBASE_DATABSE_URL).build();
// Check to make sure we don't initialize firebase app each time webpage
// is refreshed
if (!exists) {
// If firebase app doesn't exist then initialize it here and set
// exists to true
FirebaseApp.initializeApp(options);
exists = true;
}
// Call this to begin listening *notify* node in firebase database for notifications
addNotificationListener(request, response);
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Build apache httpclient POST request
HttpClient client = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(ENDPOINT_URL);
//Get the required id stored in lastMsgId tree map here
if (!(chatLogs.getLastMsgIdTreeMap().isEmpty())) {
sendToID = chatLogs.getLastMsgIdTreeMap().firstKey();
lstmsg = chatLogs.getLastMsgIdTreeMap().get(sendToID);
}
//Set up a unique id with concatenating sendToID and lstmsg
uniqueID = sendToID + lstmsg;
//Set up a previous id to check with unique id. To avoid instant duplicate notifications
previousID = fcmHelper.getPreviousid();
// Check uniqueId and PreviousID beforeSending
if (!(uniqueID.equals(previousID))) {
fcmHelper.setPreviousid(uniqueID);
//Check if device token and user Id hashmap is not null
if (!(userLogs.getUserIdAndFcmTokenHashMap().isEmpty())) {
//Get the device token of sendTo Id here
deviceToken = userLogs.getUserIdAndFcmTokenHashMap().get(sendToID);
// Create JSON object for downstream data/notification
JSONObject mainNotificationJsonObj = new JSONObject();
JSONObject outerBaseJsonObj = new JSONObject();
try {
// Notification payload has 'title' and 'body' key
mainNotificationJsonObj.put(TITLE, NEW_MESSAGE_RECEIVED);
mainNotificationJsonObj.put(BODY, lstmsg);
mainNotificationJsonObj.put(NOTIFICATION_SOUND, NOTIFICATION_SOUND_TYPE_DEFAULT);
//mainNotificationJsonObj.put(TAG, fcmHelper.getFcmTagId());
System.out.println("This is sentBy id =" + fcmHelper.getFcmTagId());
// This will be used in case of both 'notification' or 'data' payload
outerBaseJsonObj.put(TO, deviceToken);
// Set priority of notification. For instant chat setting
// high will
// wake device from idle state - HIGH BATTERY DRAIN
outerBaseJsonObj.put(PRIORITY_KEY, PRIORITY_HIGH);
// Specify required payload key here either 'data' or
// 'notification'. We can even use both payloads in single
// message
outerBaseJsonObj.put(NOTIFICATION, mainNotificationJsonObj);
} catch (JSONException e) {
e.printStackTrace();
}
// Setup http entity with json data and 'Content-Type' header
StringEntity requestEntity = new StringEntity(outerBaseJsonObj.toString(),
ContentType.APPLICATION_JSON);
// Setup required Authorization header
post.setHeader(AUTHORIZATION, FIREBASE_SERVER_KEY);
// Pass setup entity to post request here
post.setEntity(requestEntity);
// Execute apache http client post response
HttpResponse fcmResponse = client.execute(post);
// Get status code from FCM server to debug error and success
System.out.println(RESPONSE_CODE + fcmResponse.getStatusLine().getStatusCode());
// Get response entity from FCM server and read throw lines
BufferedReader rd = new BufferedReader(new InputStreamReader(fcmResponse.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
if (response != null) {
// Print out the response to webpage
PrintWriter out;
out = response.getWriter();
out.println(result);
System.out.println("This is Result - " + result);
}
} else {
//Abort this process if conditions not met
post.abort();
System.out.println(THIS_MSG_ALREADY_SENT);
}
}
}
/*
* This is the main method to be called to setup notifications listener on server startup
*/
private void addNotificationListener(HttpServletRequest request, HttpServletResponse response) {
//Initialize Value event listener
lastMsgListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot arg0) {
// Clear idLastMessagerecivedhash map if not null
if (lastMsgIdTreeMap != null) {
lastMsgIdTreeMap.clear();
}
//Get lastmsg to be sent as notification here
lstmsg = (String) arg0.child(LAST_MESSAGE).getValue();
//Get sendToID here
String sendToID = (String) arg0.child(SEND_TO).getValue();
//Get Sent by ID here
sentBy = (String) arg0.child(SENT_BY).getValue();
//Set fcmTag ID here
fcmHelper.setFcmTagId(sentBy);
//Check if lstmsg is not null
if (lstmsg != null) {
// Create lastmsgTimestampHashMap here
lastMsgIdTreeMap.put(sendToID, lstmsg);
}
//Check for null again
if (lastMsgIdTreeMap != null) {
chatLogs.setLastMsgIdTreeMap(lastMsgIdTreeMap);
}
try {
doPost(request, response);
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onCancelled(DatabaseError arg0) {
}
};
//Set up database reference to notify node here
messageRef = FirebaseDatabase.getInstance().getReference().child(NOTIFY);
//Add value listener to database reference here
messageRef.addValueEventListener(lastMsgListener);
}
"Java servlet is just a personal test. Some parts have been edited or removed to only give an idea about it's setup this is in no way production ready servlet please don't just copy - paste. I encourage you to understand and build your own."
Edit: you should take a look at Firebase Cloud Functions, which let you do that without having to create a Node.js server