I'm implementing a third part service in my app (FreshChat,a service that let you integrate an helpdesk in an app or website),and all is going fine,except for the push notifications for chats. Freshchat work via Firebase (And the firebase push notifications don't give problems) but freshat notifications don't work. I followed the official documentation of freshchat but there are deprecated methods and definitely don't work (I tryed a lot)
Here's the Firebase Cloud Messaging code:
public class FireBase extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage message) {
super.onMessageReceived(message);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "channel_id")
.setContentTitle(message.getNotification().getTitle())
.setContentText(message.getNotification().getBody())
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setStyle(new NotificationCompat.BigTextStyle())
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(true);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
And the extract from FreshChat documentation:
7.1 Connecting Freshchat with FCM
If you haven’t already integrated FCM, do so by following the instructions here. After following FCM steps for integration, follow these 2 steps to connect Freshchat and FCM
Step 1. Send Registration TokenIn the app’s implementation of FirebaseInstanceIdService, send the token to Freshchat as follows
Java
#Override
public void onTokenRefresh() {
String token = FirebaseInstanceId.getInstance().getToken();
Freshchat.getInstance(this).setPushRegistrationToken(token);
}
Step 2 : Handle FCM MessageIn the app’s implementation of FirebaseMessagingService, pass the RemoteMessage object to Freshchat if it is a Freshchat notification.
Java
public void onMessageReceived(RemoteMessage remoteMessage) {
if (Freshchat.isFreshchatNotification(remoteMessage)) {
Freshchat.getInstance(this).handleFcmMessage(context, remoteMessage);
} else {
//Handle notifications with data payload for your app
}
}
I tryed to do it via the documentation,but simply don't work,can you help me? Thank you in advance!
Here' also the full FreshChat documentation: https://support.freshchat.com/support/solutions/articles/229319-freshchat-android-sdk-integration-steps
Try adding this in your default activity, it works for me.
FirebaseInstanceId.getInstance().getInstanceId()
.addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
#Override
public void onComplete(#NonNull Task<InstanceIdResult> task) {
if (!task.isSuccessful()) {
Log.e(TAG, "getInstanceId failed", task.getException());
return;
}
// Get new Instance ID token
String token = task.getResult().getToken();
Freshchat.getInstance(this).setPushRegistrationToken(token);
Log.e("Token", token.toString());
}
});
Hope this helps you. Happy coding!!
Related
I made an android app using fcm subscribed to topic.
And here is a part of my code in FirebaseMessagingService.
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
mApplication = (ApplicationAVL)getApplication();
Log.d("FCM received === ", "ok");
cancelNotification();
ApplicationAVL mApplication = (ApplicationAVL) getApplication();
checkPollingService = isMyServiceRunning(AVLPollingService.class);
if(!mApplication.isPollingNow() || !checkPollingService){
EventBus.getDefault().post(new FcmToPollingEvent());
}
}
There is no codes for notification, but notification message always show also after closed app.
cancelNotification() is a method for remove notification I tried, but it doesn't work.
public void cancelNotification(){
String ns = NOTIFICATION_SERVICE;
NotificationManager nMgr = (NotificationManager)getSystemService(ns);
nMgr.cancelAll();
}
UnsubscribeToTopic onDestory, but it doesn't work, neither.
How can I disable fcm notification ??
Please help me...
I am trying to understand you question. Based on the title of the question, the answer is to work on the message(payload) which comes from server or other source. put "silent":"true" in data message as the following example:
{
"data": {
"title": "afruz",
"body" : "hello!",
"silent":"true"
}
"registration_ids" : [""]
}
The push notification will invoke onMessageReceived without any message showing on top bar.
If you concern about unsubscribing topic from fcm, you can try to do it at application onPaused instead of onDestroid.
Hopefully, my answer is helpful to you.
I have an android app that successfully receives notifications from the Firebase console. I now intend to build a nodejs server where we can send these notifications to save logging into the firebase console, however, it appears that the node.js library 'firebase-admin' only supports sending to individual device ids or topics rather than all devices as per the console.
So I've made a nodejs service to send to topic 'all', and tried to alter android to receive these notifications, however I get no notifications on my device from this nodejs server.
Here is my server code:
var admin = require("firebase-admin");
var serviceAccount = require("./firebase-privatekey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://myapp-android-xxx.firebaseio.com"
});
var payload = {
notification: {
title: "Account Deposit",
body: "A deposit to your savings account has just cleared."
},
data: {
account: "Savings",
balance: "$3020.25"
},
topic: "all",
};
admin.messaging().send(payload)
.then(function(response) {
console.log("Successfully sent message:", response);
})
.catch(function(error) {
console.log("Error sending message:", error);
});
This is the android code that worked with the console notifications:
public class MyNotificationService extends FirebaseMessagingService {
public MyNotificationService() {
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d("Firebase", "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d("Firebase", "Message data payload: " + remoteMessage.getData());
handleNow(remoteMessage.getData(), remoteMessage.getNotification().getBody());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d("Firebase", "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
}
public void handleNow(Map<String, String> data, String title) {
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
int notificationId = 1;
String channelId = "channel-01";
String channelName = "Channel Name";
int importance = NotificationManager.IMPORTANCE_HIGH;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(
channelId, channelName, importance);
notificationManager.createNotificationChannel(mChannel);
}
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), channelId)
.setSmallIcon(R.drawable.myapp_notification_icon)
.setBadgeIconType(R.drawable.myapp_notification_icon)
.setContentTitle(title)
.setContentText(data.get("information"));
notificationManager.notify(notificationId, mBuilder.build());
}
}
and this is the new (Additional not replaced) code, with the intention of receiving topic messages:
#Override
protected void onCreate(Bundle savedInstanceState) {
//other code...
FirebaseMessaging.getInstance().subscribeToTopic("all")
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
System.out.println("win");
} else {
System.out.println("fail");
}
}
});
}
The nodejs server tells me it was a successful send of a message, yet a breakpoint on either the win or fail message never gets hit on android
I had quite the same problem. The solution I found was adding:
<service
android:name=".java.MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
to AndroidManifest.xml and:
#Override
public void onDeletedMessages() {
super.onDeletedMessages();
}
to MyFirebaseMessagingService.
According to the docs.
Override onDeletedMessages
In some situations, FCM may not deliver a message. This occurs when
there are too many messages (>100) pending for your app on a
particular device at the time it connects or if the device hasn't
connected to FCM in more than one month. In these cases, you may
receive a callback to FirebaseMessagingService.onDeletedMessages()
When the app instance receives this callback, it should perform a full
sync with your app server. If you haven't sent a message to the app on
that device within the last 4 weeks, FCM won't call
onDeletedMessages().
I'm just using firebase, now I've managed to create user authentication and have a few push notification questions in the firebase.
Before I followed the tutorial here, and it worked I was very happy. But apparently after I logout and try push notification, I still still receive the notification.
So my question is also pretty much about push notifications, namely:
How to make the notification only enter when I'm logged in?
How do I target the notification with the registered UID only?
Is it necessary to make notifications from firebase, so it can't be as straightforward as an automatic chat application?
Here's the code I've made:
MyFirebaseInstanceldService.java
public class MyFirebaseInstanceldService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(refreshedToken);
}
private void sendRegistrationToServer(String refreshedToken) {
}
}
MyFirebaseMessaginService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public MyFirebaseMessagingService() {
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
sendNotification(Objects.requireNonNull(remoteMessage.getNotification()).getBody());
}
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, HotelManagementActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setSmallIcon(R.drawable.rotarylogo);
notificationBuilder.setContentTitle("Rotary Barcode");
notificationBuilder.setContentText(messageBody);
notificationBuilder.setAutoCancel(true);
notificationBuilder.setSound(defaultSoundUri);
notificationBuilder.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
assert notificationManager != null;
notificationManager.notify(0, notificationBuilder.build());
}
}
If there is anything I still need to add, just say for the other code. I thank you very much for wanting to help me who is still a beginner.
How to make the notification only enter when I'm logged in?
You have to handle it in a way where the token that gets generated is paired to the user that successfully logs in, making sure that you handle the logout as well.
How do I target the notification with the registered UID only?
Depending on which server you are using, you could just pair the token to the UID of the user (I presume you are using Firebase Auth). For example, what we did in our app (we're using Firebase DB) was as soon as the user gets to the home screen (successfully signs in), we submit the token to the DB, where the key is the uid. This way, we can easily get the token by specifying the uid.
Is it necessary to make notifications from firebase, so it can't be as straightforward as an automatic chat application?
I'm not sure what you mean by this one.
In general, having 3 questions in a single post is not advised here in Stack Overflow. I would strongly suggest that moving forward that you split each question into their own post as much as possible.
I've connected an Android app to Google Firebase Cloud Messaging service (FCM) following this guide,
and I've followed this answer to setup the connection between FCM & AWS SNS.
I could successfully receive message sent from FCM console but not from AWS SNS console.
The message delivery status logged on AWS showed SUCCESS for every message I've sent while no notification was shown on my device.
Is there a way to check what's going on?
I faced the exactly the same problem, message from Firebase with device token works but somehow message from SNS to Firebase is not delivered.
I did develop iOS app as well, and at that moment, just sending "brabra" delivered message to iOS. However, FCM only accepts particular message format to test it from AWS SNS console.
Here is the example format of successful delivery of message to Android through SNS and FCM.
{
"GCM": "{\"notification\": { \"body\": \"Sample message for Android endpoints\", \"title\":\"Hello world\" } }"
}
The point is that we have to amend to "notification", not "data", and should have body and title in the notification.
The problem here is that AWS SNS sends what Google calls data messages.
With FCM you can send two types of messages - notifications and data. Notifications get displayed automatically by FCM while data messages do not. More on this here: https://firebase.google.com/docs/cloud-messaging/concept-options
Data messages that come in from SNS still can be handled - even if your app is in the background - by extending FirebaseMessagingService and overriding it's onMessageReceived method. More on this here: https://firebase.google.com/docs/reference/android/com/google/firebase/messaging/FirebaseMessagingService
I assume you would want your AWS SNS messages to mimic the notifications experience, namely:
See them pop up when the app is in the background
Have your text displayed in the notification
When the app activates you want all of the messages cleared out from
the drawer
To achieve this you'll want to do three things.
Firstly - you'll want to start tracking if your app is currently visible or not. The details on how to reliably detect this you can find here: https://stackoverflow.com/a/18469643/96911
Secondly - you'll want to handle data messages from AWS SNS by posting a notification, but only when your app is in the background:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
static protected int id = 0;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if (!MyApplication.isActivityVisible()) {
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle(getString(R.string.app_name))
.setSmallIcon(R.drawable.notification_icon);
String message = remoteMessage.getData().get("default");
mBuilder.setContentText(message);
Intent resultIntent = new Intent(this, MainActivity.class);
PendingIntent resultPendingIntent =
PendingIntent.getActivity(
this,
0,
resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.notify(id ++, mBuilder.build());
}
}
}
And lastly - you'll want to clear out all of the notifications from the drawer when the user clicks on one of them. Combined with the visibility tracking I linked just above the activity that responds to the notifications should have the following onResume method:
#Override
protected void onResume() {
super.onResume();
MyApplication.activityResumed();
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotificationManager.cancelAll();
}
It's been a long time since you asked this question but it was so painful for me to get to the bottom of this I decided to answer anyway. I hope this helps you or somebody tearing their hair out trying to make this thing work (cause making iOS work was a breeze, sheesh).
You can use this video tutorial https://youtu.be/iBTFLu30dSg with English subtitles of how to use FCM with AWS SNS step by step and example of how to send push notifications from AWS console. It works well for me and I successfully received push notification from SNS console and from my code on the mobile device
Simply using this JSON format:
{
"GCM": "{ \"notification\": { \"body\": \"Sample message for Android endpoints\",\"title\": \"Sample message for Android endpoints\"}}"
}
To get the Data from AWS SNS Console follow the below step:
1) Add the Project in FCM and Use Legacy server key for AWS SNS.
2) Get the Device token by using the below code:
String deviceToken = FirebaseInstanceId.getInstance().getToken();
3) Implement the below code in your application
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
sendRegistrationToServer(refreshedToken);
}
private void sendRegistrationToServer(String token) {
// TODO: Implement this method to send token to your app server.
}
}
4) Override onMessageReceived() its invoke when notification is received:
public class AppFirebaseMessagingService extends FirebaseMessagingService {
static protected int id = 0;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
//remoteMessage.getNotification().getBody()
if (remoteMessage.getData().get("default").length() > 0) {
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
Uri ringNotificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notifyBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("ApplicationName")
.setContentText(remoteMessage.getData().get("default"))
.setAutoCancel(true)
.setSound(ringNotificationSound)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(id++, notifyBuilder.build());
}
}
}
When We get the Notification from AWS SNS Service then we use remoteMessage.getData().get("default") for reading the message from AWS.
I have a Problem with Firebase Cloud Messaging:
I implemented a little App with the 2 extended Services FirebaseInstanceIdService and FirebaseMessagingService.
If I start the application and send a notification via
Firebase Console, I get the notification on my device.
Everything works.
If I open the App again, it hangs up and produces a black
screen. There is no output on the Android Studio console then.
I also don't get a second notification from Firebase console.
Then I get a Dialog: "The Application does not react etc"
After opening the app again it works fine again.
I also do not get an Token in the Logcat (?)
Firebase InstanceIdService:
public class InstanceIdService extends FirebaseInstanceIdService
{
private static final String TAG = "InstanceIdService";
#Override
public void onTokenRefresh()
{
String token = FirebaseInstanceId.getInstance().getToken();
Log.e(TAG, "!!!!!!!!!!!!!!!!!! Got token: " + token);
}
}
FirebaseMessagingService:
public class MyFirebaseMessagingService extends FirebaseMessagingService
{
#Override
public void onMessageReceived(RemoteMessage remoteMessage)
{
sendNotification(remoteMessage);
}
public void sendNotification(RemoteMessage remoteMessage)
{
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle(remoteMessage.getFrom())
.setContentText(remoteMessage.getNotification().getBody())
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
The only errors on the Android Studio Console is
"Failed to load module descriptor class" but that is
a known bug.
I hope you can help me.
Best Regards,
Felix
EDIT: error message From the Firebase console:
Exception java.lang.RuntimeException: Parcel android.os.Parcel#4215be98: Unmarshalling unknown type code 1936206469 at offset 68
android.os.Parcel.readValue (Parcel.java:2087)
android.os.Parcel.readArrayMapInternal (Parcel.java:2321)
android.os.Bundle.unparcel (Bundle.java:249)
android.os.Bundle.getString (Bundle.java:1118)
com.google.firebase.messaging.FirebaseMessagingService.zzT ()
com.google.firebase.messaging.FirebaseMessagingService.zzm ()
com.google.firebase.iid.zzb$2.run ()
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1112)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:587)
java.lang.Thread.run (Thread.java:841)
I also do not get an Token in the Logcat (?)
onTokenRefresh() method is called when generating a new token for you. It is not called everytime you open the app.
However you can get the token using FirebaseInstanceId.getInstance().getToken();
If I start the application and send a notification via Firebase Console, I get the notification on my device. Everything works. If I open the App again, it hangs up and produces a black screen.
I faced a similar issue, this generally happens if you have no or slow internet connection. No solution yet. :(