I am trying to use the Firebase messaging in Oreo device, but even though the channel is being created I am unable to receive the data in the proper channel. (Note: this is not working in the emulator, but only on device)
This is my application class:
public class FCMPlayApp extends Application {
#Override
public void onCreate() {
super.onCreate();
FirebaseMessaging.getInstance().subscribeToTopic(MessagingConstants.TOPIC_ALL);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel();
}
}
#RequiresApi(Build.VERSION_CODES.O)
private void createNotificationChannel() {
NotificationChannel allChannel = new NotificationChannel(
"channel_all", "All Channel", NotificationManager.IMPORTANCE_HIGH);
((NotificationManager) getSystemService(NOTIFICATION_SERVICE))
.createNotificationChannel(allChannel);
}
}
Here is my messaging service class:
public class MessagingService extends FirebaseMessagingService {
private static final String TAG = "MessagingService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d(TAG, "Message received for topic: " + remoteMessage.getFrom());
}
}
Here is what I have defined in the Android manifest for the default channel:
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="channel_all"/>
Here is what I am sending using Postman tool for the push message:
{
"to": "/topics/all",
"data": {
"msg_bg_color" : "#ABCDEF"
},
"notification": {
"body": "Hello",
"title": "This is test message."
},
"android_channel_id" : "channel_all"
}
Can you please let me know as to what I am missing.
As Diego has mentioned:
android_channel_id should go inside the notification payload
This is the answer. Once Diego answer, I will mark it as an answer. This is just a reference for others.
Related
I am using Azure Hubs to send notifications. I am able to receive the notification and it displays on the device when I pull down the notifications window. However, I do not see the notification display at the top of the screen as expected. I even "locked" the screen and it didn't display. I got the notification sound and my logs show I received it.
Screen showing received notification
My FirebaseMessageService:
using System;
using System.Linq;
using WindowsAzure.Messaging;
using Android.App;
using Android.Content;
using Android.Support.V4.App;
using Android.Util;
using Firebase.Messaging;
using IDEQ.AQI.Pages;
namespace IDEQ.AQI.Droid
{
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class FirebaseService : FirebaseMessagingService
{
const string Tag = "FirebaseMsgService";
public override void OnNewToken(string token)
{
// NOTE: save token instance locally, or log if desired
SendRegistrationToServer(token);
}
private void SendRegistrationToServer(string token)
{
try
{
var hub = new NotificationHub(Constants.NotificationHubName, Constants.ListenConnectionString, this);
// register device with Azure Notification Hub using the token from FCM
var registration = hub.Register(token, Constants.SubscriptionTags);
// subscribe to the SubscriptionTags list with a simple template.
var pnsHandle = registration.PNSHandle;
var templateReg = hub.RegisterTemplate(pnsHandle, "defaultTemplate", Constants.FCMTemplateBody, Constants.SubscriptionTags);
}
catch (Exception e)
{
Log.Error(Constants.DebugTag, $"Error registering device: {e.Message}");
}
}
public override void OnMessageReceived(RemoteMessage message)
{
base.OnMessageReceived(message);
string messageBody;
Log.Info(Tag, "From: " + message.From);
if (message.GetNotification() != null)
{
Log.Info(Tag, "Notification Message Body: " + message.GetNotification().Body);
messageBody = message.GetNotification().Body;
}
// NOTE: test messages sent via the Azure portal will be received here
else
{
messageBody = message.Data.Values.First();
}
// convert the incoming message to a local notification
SendLocalNotification(messageBody);
// send the incoming message directly to the MainPage
SendMessageToMainPage(messageBody);
}
private void SendLocalNotification(string body)
{
try
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
intent.PutExtra("message", body);
var requestCode = new Random().Next();
var pendingIntent = PendingIntent.GetActivity(this, requestCode, intent, PendingIntentFlags.OneShot);
var notificationBuilder = new NotificationCompat.Builder(this, Constants.NotificationChannelId)
.SetContentTitle("IDEQ Alert")
.SetSmallIcon(Resource.Drawable.ic_launcher)
.SetContentText(body)
.SetAutoCancel(true)
.SetShowWhen(false)
.SetContentIntent(pendingIntent);
var notificationManager = NotificationManagerCompat.From(this);
notificationManager.Notify(0, notificationBuilder.Build());
}
catch (Exception e)
{
Log.Error(Tag, e.ToString());
}
}
private void SendMessageToMainPage(string body)
{
(Xamarin.Forms.Application.Current.MainPage as MainPage)?.AddMessage(body);
}
}
}
//My main activity where I create the channel:
private void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var channel = new NotificationChannel(Constants.NotificationChannelId, Constants.NotificationChannelName, NotificationImportance.Default)
{
Description = string.Empty
};
var notificationManager = (NotificationManager) GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
Notification in your system tray will only be displayed if application is in background or turned off. If your application is running, your OnMessageRecieved method will get hit, however Android will not display notification in the system try. This is how life cycle of push notification works in Android.
The only way u can display notification in system tray when application in in foreground is when you force Local Notification like you did in SendLocalNotification method.
My notification work if the app is in the background but it doesn't work in the foreground
this is my MyFirebaseMessagingService class:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static final String TAG = "MessagingService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
String title = remoteMessage.getNotification().getTitle();
String message = remoteMessage.getNotification().getBody();
String uid = remoteMessage.getData().get("uid");
String click_action = remoteMessage.getNotification().getClickAction();
Log.d(TAG, "onMessageReceived: "+title + message + uid+" "+click_action);
Intent intent = new Intent(click_action);
if (click_action.equals("com.example.android.ProfileFriends")){
intent.putExtra("uid",uid);
}else if (click_action.equals("com.example.android.ChatActivity")){
}
// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setContentTitle(title);
notificationBuilder.setContentText(message);
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher_event);
notificationBuilder.setPriority(NotificationCompat.PRIORITY_HIGH);
notificationBuilder.setCategory(NotificationCompat.CATEGORY_MESSAGE);
notificationBuilder.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0,notificationBuilder.build());
}
}
Please, how can i resolve this problem?
FCM has different behaviours for app status (foreground and background / killed).
You should handle this by the payload you sent from server, according to your use case.
The msg sent from server has to be sent in either "notification" or "data" format, from dashboard or server side api.
Note: From firebase dashobard you can only send "notification" body and not data. In such cases, FCM will directly display the notif without giving a callback to your app.
Server side
Below are sample formats :
Notification Type Format
Note : Android System will by default display the notification in the notification tray and you don't need to display it.
{
"to": "your_token_id",
"notification" : {
"title" : "FCM Notification title!",
"body" : "FCM Notification subtext!",
"content_available" : true,
"priority" : "high"
}
}
Data Format (For receiving callback in app, in foreground and background)
Note : You have to handle callback and display notif on your own.
{
"to": "your_token_id",
"data" : {
"title" : "FCM Notification Title ",
"subtext" : "FCM Notification Sub Title",
"type" : "999",
"priority" : "high"
}
}
Android Client
To handle the payload received in your Android receiver, checl the official guide here
/* The class extends FirebaseMessagingService() */
override fun onMessageReceived(remoteMessage: RemoteMessage) {
Log.d(TAG, "From: ${remoteMessage.from}")
// Check if message contains a data payload.
remoteMessage.data.isNotEmpty().let {
Log.d(TAG, "Message data payload: " + remoteMessage.data)
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use WorkManager.
scheduleJob()
} else {
// Handle message within 10 seconds
handleNow()
}
}
// Check if message contains a notification payload.
remoteMessage.notification?.let {
Log.d(TAG, "Message Notification Body: ${it.body}")
}
// 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.
}
Check the documentation here
I want to integrate fcm for having push notification functionality in my app. But the problem is my fcm token is not getting generated at all. I used the same code I used in this project into a new project and it worked without any issue.
But with this project I have tried everything to no result at all.
I tried with both the deprecated onTokenRefresh() method as well as the new onNewToken() method but none of them is working for me.
Below is the code for the same.
public class CustomFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
// TODO(developer): Handle FCM messages here.
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());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d("Firebase", "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.
}
#Override
public void onNewToken(String s) {
super.onNewToken(s);
Log.d("token",s);
}
}
And this is the code with onTokenRefresh() method
public class MyFirebaseInstanceIdService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
super.onTokenRefresh();
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d("Firebase", "Refreshed token: " + refreshedToken);
}
}
I have declared both services in the manifest too.
<service android:name=".notification.CustomFirebaseMessagingService"
android:stopWithTask="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name=".notification.MyFirebaseInstanceIdService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
What I have tried
Deleted the project on console and creating again
Copying whole project to a new folder and open again in Android Studio
Tried with both of the above service
Tried calling FirebaseInstanceId.getToken() but this gives null pointer exception.
Aside from the implementation errors, have a look at how instance ID works: https://developers.google.com/instance-id/, check the chapter Instance ID lifecycle at the bottom.
I can see 2 points where it might go wrong:
You don't have a connection with the Google servers. Check if you have a working internet connection by opening the device and opening a webpage. Also take proxies and firewalls into account, those might block your traffic (for example, if you are in China, the Great Firewall might block your connection with the Instance ID servers).
Make sure you don't already have a token. This is quite a common error. You implement the ID token service, and run the app. It works fine, now you want to send the token to the server, and write the code for it. When you run the app again, you will see no connection to the server, and think there's an issue with your implementation.
What actually happened, is that you already got your token on the first run, and it was cached by the app. The second time it already has a token, and the onNewToken() will not be called.
If you uninstall the app, and install it again, it will ask for a new token on launch.
Finally got the solution to my problem. I got this hint when I was trying to integrate OneSignal notification sdk. The problem was that I had the below code in the application tag of manifest.
tools:node="replace"
This was written in OneSignal docs.
Make sure you are not replacing the tag in your AndroidManifest.xml with tools:node="replace"
As OneSignal was also internally using FireBase I thought to give it a try with the firebase directly and it worked after I removed it.
Hope this will help someone else too
As said by #Nilesh Rathod FirebaseInstanceIdService is depreciated. So no you need only one service in the manifest.
Try this way.
1. First Create a Service
public class YourService extends FirebaseMessagingService {
public static int NOTIFICATION_ID = 1;
#Override
public void onNewToken(String s) {
super.onNewToken(s);
}
#Override
public void onMessageReceived(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 mNotifyBuilder = new NotificationCompat.Builder(this, "2")
.setSmallIcon(R.drawable.your_icon)
.setContentTitle(remoteMessage.getNotification().getTitle())
.setContentText(remoteMessage.getNotification().getBody())
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (NOTIFICATION_ID > 1073741824) {
NOTIFICATION_ID = 0;
}
Objects.requireNonNull(notificationManager).notify(NOTIFICATION_ID++, mNotifyBuilder.build());
}
}
Now add this to Manifest
<service
android:name=".YourService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
the generate of token for firebase is in first install of app or when you delete the cache for app ,this example of code work for me
public class MyFirebaseInstanceIdService extends FirebaseInstanceIdService {
SharedPreferences sharedPreferences1;
SharedPreferences.Editor editor1;
private static final String PREF_NAME1 = "prefs_token";
private static final String KEY_FCM = "devices_token";
//this method will be called
//when the token is generated
#Override
public void onTokenRefresh() {
sharedPreferences1 = getSharedPreferences(PREF_NAME1, Context.MODE_PRIVATE);
editor1 = sharedPreferences1.edit();
super.onTokenRefresh();
//now we will have the token
String token = FirebaseInstanceId.getInstance().getToken();
editor1.putString(KEY_FCM,token.toString());
editor1.apply();
//for now we are displaying the token in the log
//copy it as this method is called only when the new token is generated
//and usually new token is only generated when the app is reinstalled or the data is cleared
Log.d("MyRefreshedToken", token);
String device_token = sharedPreferences1.getString(KEY_FCM, "");
}
}
The onTokenRefresh/onNewToken methods are only called when a token is generated. Most of the time a token just exists, and is not modified. During that time, onTokenRefresh/onNewToken won't be called.
So most likely, your token was generated when you first add the app, before you had the onTokenRefresh/onNewToken. So to now get the token, you can do two things:
Uninstall and reinstall the app. Deleting the app will delete the existing token, then it will generate a new token on the reinstall, and call your onTokenRefresh/onNewToken.
Also request the token in e.g. your MainActivity.onCreate.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
...
String iidToken = FirebaseInstanceId.getInstance().getToken();
Log.d("Firebase", "Got token: " + iidToken);
Create two java classes and one interface in APP
Interface:
public interface FCMTokenInterface {
void onTokenReceived(String token);
void onFailure();
}
Token Listener Class:
public class MyInstanceIDListenerService extends FirebaseInstanceIdService {
private static FCMTokenInterface fcmTokenCallback;
private static Handler handlerOs = new Handler();
private static int delay=20000;
private static final String TAG = "MyFirebaseIIDService";
private static final String FRIENDLY_ENGAGE_TOPIC = "friendly_engage";
#Override
public void onTokenRefresh() {
String token = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "FCM Token: 3" + token);
//putting token in preference
Prefs.putString(Constant.FCM_TOKEN,token);
FirebaseMessaging.getInstance()
.subscribeToTopic(FRIENDLY_ENGAGE_TOPIC);
}
public static void setCallback(FCMTokenInterface callback) {
try {
String token = FirebaseInstanceId.getInstance().getToken();
if (token != null && !token.isEmpty()) {
//putting token in preference
Prefs.putString(Constant.FCM_TOKEN,token);
callback.onTokenReceived(token);
return;
}
} catch (Exception e) {
retry(callback);
Log.v("SetCallback EXP= ", e.toString());
}
fcmTokenCallback = callback;
// startHandler();
}
public static void retry(FCMTokenInterface callback)
{
setCallback(callback);
}
private static void startHandler() {
handlerOs.postDelayed(new Runnable() {
#Override
public void run() {
retry(fcmTokenCallback);
// fcmTokenCallback.onFailure();
fcmTokenCallback = null;
}
}, delay);
}
private static void clearHandler() {
handlerOs.removeCallbacksAndMessages(null);
}
}
Message Receiving Class:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFMService";
String CHANNEL_ID = "com.app.app";
NotificationChannel mChannel;
private NotificationManager mManager;
private String title, msg, actionCode;
private int badge = 0;
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Handle data payload of FCM messages.
Log.d(TAG, "FCM Message Id: " + remoteMessage.getMessageId());
Log.d(TAG, "FCM Notification Message: " + remoteMessage.getData() + "...." +
remoteMessage.getFrom());
if (remoteMessage.getData() != null) {
Map<String, String> params = remoteMessage.getData();
JSONObject object = new JSONObject(params);
//Log.e("JSON_OBJECT", object.toString());
title = object.optString("title","");
actionCode = object.optString("action_code", "");
msg = object.optString("body", "");
if (remoteMessage.getData().containsKey("badge")) {
badge = Integer.parseInt(remoteMessage.getData().get("badge"));
//Log.d("notificationNUmber", ":" + badge);
setBadge(getApplicationContext(), badge);
Prefs.putBoolean(Constant.HAS_BADGE,true);
}
if (!(title.equals("") && msg.equals("") && actionCode.equals(""))) {
createNotification(actionCode, msg, title);
}
else {
//Log.e("Notification", "Invalid Data");
}
}
}
public void createNotification(String action_code, String msg, String title) {
Intent intent = null;
intent = new Intent(this, HomeActivity.class);
intent.putExtra(Constant.ACTION_CODE, action_code);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel androidChannel = new NotificationChannel(CHANNEL_ID,
title, NotificationManager.IMPORTANCE_DEFAULT);
// Sets whether notifications posted to this channel should display notification lights
androidChannel.enableLights(true);
// Sets whether notification posted to this channel should vibrate.
androidChannel.enableVibration(true);
// Sets the notification light color for notifications posted to this channel
androidChannel.setLightColor(Color.GREEN);
// Sets whether notifications posted to this channel appear on the lockscreen or not
androidChannel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
getManager().createNotificationChannel(androidChannel);
Notification.Builder nb = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
.setContentTitle(title)
.setContentText(msg)
.setTicker(title)
.setShowWhen(true)
.setSmallIcon(R.mipmap.ic_small_notification)
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(),
R.mipmap.ic_launcher_round))
.setAutoCancel(true)
.setContentIntent(contentIntent);
getManager().notify(101, nb.build());
} else {
try {
#SuppressLint({"NewApi", "LocalSuppress"}) android.support.v4.app.NotificationCompat.Builder notificationBuilder = new android.support.v4.app.NotificationCompat.Builder(this).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.setSmallIcon(R.mipmap.ic_small_notification)
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(),
R.mipmap.ic_launcher_round))
.setContentTitle(title)
.setTicker(title)
.setContentText(msg)
.setShowWhen(true)
.setContentIntent(contentIntent)
.setLights(0xFF760193, 300, 1000)
.setAutoCancel(true).setVibrate(new long[]{200, 400});
/*.setSound(Uri.parse("android.resource://"
+ getApplicationContext().getPackageName() + "/" + R.raw.tone));*/
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify((int) System.currentTimeMillis() /* ID of notification */, notificationBuilder.build());
} catch (SecurityException se) {
se.printStackTrace();
}
}
}
private NotificationManager getManager() {
if (mManager == null) {
mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
return mManager;
}
}
Implement Interface on your Splash:
class SplashActivity : AppCompatActivity(), FCMTokenInterface {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_splash)
MyInstanceIDListenerService.setCallback(this)
}
override fun onFailure() {
Log.d("Token", "Unable to get token.")
}
override fun onTokenReceived(token: String?) {
Log.d("Token", token)
Prefs.putString(Constant.FCM_TOKEN, token)
}
}
Manifest under Application TAG
<service android:name="fcm.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name="fcm.MyInstanceIDListenerService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#mipmap/ic_launcher_round" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
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().
Sir I am trying to send upstream message from my android phone but failed to do so.Don't know where i am wrong.
Here is my code:
public class MainActivity extends AppCompatActivity {
Button button;
private AtomicInteger msgId;
FirebaseMessaging fm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FirebaseMessaging.getInstance().subscribeToTopic("hello");
FirebaseInstanceId.getInstance().getToken();
msgId = new AtomicInteger();
button = (Button) findViewById(R.id.click);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getApplicationContext(),""+msgId,Toast.LENGTH_SHORT).show();
fm = FirebaseMessaging.getInstance();
RemoteMessage message=new RemoteMessage.Builder("<my sender id>#gcm.googleapis.com")
.setMessageId(Integer.toString(msgId.incrementAndGet()))
.addData("my_message", "Hello World")
.addData("my_action", "SAY_HELLO")
.build();
fm.send(message);
}
});
}
}
I had implemented onMessageSent() and onSendError() as according to docs but these methods were never called.Here is my messaging service class:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d("msg", "onMessageReceived: " + remoteMessage.getData().get("message"));
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("test")
.setContentText(remoteMessage.getData().get("message"));
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
}
#Override
public void onMessageSent(String s) {
super.onMessageSent(s);
Log.d("fcm", "onMessageSent: message sent");
Toast.makeText(getApplicationContext(), "message:" + s, Toast.LENGTH_SHORT).show();
}
#Override
public void onSendError(String s, Exception e) {
super.onSendError(s, e);
Log.d("fcm", "onSendError: erroe");
Toast.makeText(getApplicationContext(), "error:" + s, Toast.LENGTH_SHORT).show();
}
}
i am trying this from 1 week still don't know where I am wrong.Also there is nothing in logcat.please help.
You have to set TTL at your message, For Example
RemoteMessage message=new RemoteMessage.Builder("<my sender id>#gcm.googleapis.com")
.setMessageId(Integer.toString(msgId.incrementAndGet()))
.addData("my_message", "Hello World")
.addData("my_action", "SAY_HELLO")
.setTtl(86400)
.build();
setTtl(86400) this line is important ,hope it will helps.
In an effort to optimize device resources especially battery the callbacks to onMessageSent and onSendError are batched so you may not receive a callback till you send around 10 or so upstream messages.
See the docs for more.
You need to have an app server running some xmpp server to talk to the Firebase Messaging server.
Be sure to set Time-to-Live on your message. For example, new RemoteMessage.Builder(...).setTtl(<time in sec>). I have not seen this behavior documented in the FirebaseMessagingService and/or Cloud Connection Server (CCS) references.