I made apps that need to get a notification though the apps are closed. I'm using fcm to get the notification. But when the apps are removed from the recent task, I stop getting a notification. I had seen other article but I still can't get the answer to my problem.
I'm using firebase:
'com.google.firebase:firebase-messaging:11.0.2'
MyFirebaseMessagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.e(TAG, "From: " + remoteMessage.getFrom());
Log.e(TAG, "Data Payload: " + remoteMessage.getData().toString());
Log.e(TAG," remote :" +remoteMessage.toString() );
try {
JSONObject json = new JSONObject(remoteMessage.getData());
String title = json.get("title").toString();
String message = json.get("message").toString();
createNottification(title, message);
}
catch (Exception ex){}
if(remoteMessage.getNotification() != null)
Log.d(TAG, "Message Notification Body: "+remoteMessage.getNotification().getBody());
}
private void createNottification(String title,String message)
{
Uri notificationSoundURI = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);;
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(R.mipmap.pmi_launcher)
.setSound(notificationSoundURI )
.build();
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getApplicationContext());
notificationManager.notify(Config.NOTIFICATION_ID, notification);
}
}
Manifest.xml
<!-- Firebase Notifications -->
<service android:name=".services.MyFirebaseMessagingService" android:stopWithTask="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".services.MyFirebaseInstanceIDService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
first pass PendingIntent and also pass unique notification ID for generate bunch or stack of notification. also set Flags for notification Intent.so just do this in this way. Hope it helps to you and also other users.
private void sendNotification(String message,String title) {
int id = (int) System.currentTimeMillis();
Intent notificationIntent = new Intent(this, SplashActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle(title)
.setContentText(message)
//.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(image).setSummaryText(message))
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher);
} else {
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher);
}
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(id, notificationBuilder.build());
}
Related
I am sending DATA payload from Postman, so the notification should be processed in onMessageReceived regardless of whether the app is in foreground or background.
According my logs and testing, onMessageReceived is fired, but the notifications are not showing (doesn't depend if the app is in foreground or background).
in manifest I have:
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service> <!-- [END firebase_iid_service] -->
<service
android:name=".MyFirebaseInstanceIDService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
and here is MyFirebaseMessagingService.java:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
String title = "";
if (Objects.requireNonNull(remoteMessage.getData()).get("title") != null)
title = remoteMessage.getData().get("title");
String message = "";
if (Objects.requireNonNull(remoteMessage.getData()).get("message") != null)
message = remoteMessage.getData().get("message");
Log.e("notification",title);
sendNotification(title, message);
}
private void sendNotification(String title, String body) {
Intent i = new Intent(this, Novinky.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pi = PendingIntent.getActivity(this,
0, // Request code
i,
PendingIntent.FLAG_ONE_SHOT);
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,
getString(R.string.default_notification_channel_id))
.setSmallIcon(R.mipmap.ic_notify)
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setSound(sound)
.setContentIntent(pi);
NotificationManager manager =
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.notify(0, builder.build());
}
}
So I have Log.e("notification",title); there, and it is executed properly, but the notify is not received.
Before I send also a notification+data via Postman, that worked, but that is only an automatic notification not handled by app, so now I want to send only DATA payload and handle it in the app, but for some reason it doesn't work.
You need to make sure you have created your notification channel in your app. A good way to do this is as follows:
public class App extends Application {
#Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel nChan = new NotificationChannel(
getString(R.string.default_notification_channel_id),
"My_Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(nChan);
}
}
}
Creating your notification channel in the onCreate() of your app is a good idea as you don't have to worry about it for the rest of the application life time.
My notification data message is as below:
{data=
{"sender_username":null,
"image":null,
"is_background":false,
"payload":{"post_id":"1"},
"userId":2,
"title":"ABC",
"message":"Someone liked your post!",
"timestamp":"2018-06-02 10:46:50"
}
}
This message is received when app is in foreground,it received in onMessageReceived(RemoteMessage message).I also know that my this message is only received when app in foreground.
Problem
But when the app in background or closed,the notification is appear in notification tray.The problem is when I click on the notification,it doesn't launch my app,totally no response.
Here is my code:
AndroidManifest.xml
<!-- Firebase service -->
<service
android:name=".services.FirebaseMessagingService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service
android:name=".services.FirebaseInstanceIDService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
Here is how I handle the notification:
public void showNotificationMessage(final String title, final String message, final String timeStamp, Intent intent, String imageUrl) {
// Check for empty push message
if (TextUtils.isEmpty(message))
return;
// notification icon
final int icon = R.drawable.logo;
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent resultPendingIntent =
PendingIntent.getActivity(
mContext,
0,
intent,
PendingIntent.FLAG_CANCEL_CURRENT
);
final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
mContext);
final Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE
+ "://" + mContext.getPackageName() + "/raw/notification");
if (!TextUtils.isEmpty(imageUrl)) {
if (!imageUrl.equalsIgnoreCase(null) && imageUrl.length() > 4 && Patterns.WEB_URL.matcher(imageUrl).matches()) {
Bitmap bitmap = getBitmapFromURL(imageUrl);
if (bitmap != null) {
showBigNotification(bitmap, mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
} else {
showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
}
}
} else {
showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);
playNotificationSound();
}
}
private void showSmallNotification(NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
inboxStyle.addLine(message);
Notification notification;
notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)
.setAutoCancel(true)
.setContentTitle(title)
.setContentIntent(resultPendingIntent)
.setSound(alarmSound)
.setStyle(inboxStyle)
.setWhen(getTimeMilliSec(timeStamp))
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))
.setContentText(message)
.build();
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(AppConfig.NOTIFICATION_ID, notification);
}
My code run well before in 'com.google.firebase:firebase-messaging:10.2.4',the problem happen when I upgrade to 'com.google.firebase:firebase-messaging:17.0.0'.
After I looking at the same code again and again for past 2 days,I still cant figure out,where the problem came from.Somebody please help..
If possible,please give some hint about what is the possible issue that will cause this problem.
Thank you.
I can give a better idea if you can tell me From where you are calling this showNotification message, and where is your FirebaseMessagingService() class ?
But as far as i understand, the intent you are passing as parameter should specify which activity you want to open, something like this:
val intent = Intent(this#MyFirebaseMessagingService, MainActivity::class.java)// here i want to open the MainActivity on notification click
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
val pendingIntent = PendingIntent.getActivity(this#MyFirebaseMessagingService, 0, intent, PendingIntent.FLAG_ONE_SHOT)
I will get a clear view if you can show me your class where you are extending FirebaseMessagingService() class.
Hope it helps.
I have integrated Firebase Cloud Messaging with my application.
When I sent a notification from the Firebase console, if the app is in background or not opened I receive successfully the notification,
otherwise if the app is in foreground or opened, I did not receive it.
All suggestions are appreciated.
When app is in foreground, notifications are not generated themselves. You need to write some additional code. When message is received onMessageReceived() method is called where you can generate the notification. Here is the code:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d("msg", "onMessageReceived: " + remoteMessage.getData().get("message"));
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);
String channelId = "Default";
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(remoteMessage.getNotification().getTitle())
.setContentText(remoteMessage.getNotification().getBody()).setAutoCancel(true).setContentIntent(pendingIntent);;
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId, "Default channel", NotificationManager.IMPORTANCE_DEFAULT);
manager.createNotificationChannel(channel);
}
manager.notify(0, builder.build());
}
}
FirebaseMessagingService never work when the app is in foreground. In this case if you want to receive the message from FCM then WakefulBroadcastReceiver will work for you
public class FirebaseDataReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("BroadcastReceiver::", "BroadcastReceiver");
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(intent.getExtras().getString("title"))
.setContentText(intent.getExtras().getString("message"));
NotificationManager manager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
}
}
Link firebase with GCM in play store and write the below code in manifest
<receiver
android:name=".firebase.FirebaseDataReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</receiver>
I used Firebase messaging in my app and send some value with notification to my app, and when tap the notification to open a special activity.
this works just when app in forground(app is opened) and when tap the notification activity opened and show conent sended from firebase .
but i want open activity when app is closed(background).
manifest code :
<activity
android:name=".activity.NotificationActivity"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="activity_post" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
MyFirebaseMessagingService class code:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Map<String,String> data=remoteMessage.getData();
switch (data.get(DESTINATION_TYPE)){
case DESTINATION_TYPE_ACTIVITY:
String activity=data.get(DESTINATION);
switch (activity){
case ACTIVITY_POST:
Intent showPostActivityIntent=new Intent(this, NotificationActivity.class);
String postTitle=data.get(EXTRA_POST_TITLE);
String postContent=data.get(EXTRA_POST_CONTENT);
String postImageUrl=data.get(EXTRA_POST_IMAGE_URL);
showPostActivityIntent.putExtra("title",postTitle);
showPostActivityIntent.putExtra("content",postContent);
showPostActivityIntent.putExtra("image_url",postImageUrl);
showPostActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
sendNotification(remoteMessage.getNotification().getBody(),showPostActivityIntent);
}
break;
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
private void sendNotification(String messageBody,Intent intent) {
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)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))
.setContentTitle("Tip Top App")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
Someone please help to solve it.
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// checking for type intent filter
if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {
// gcm successfully registered
// now subscribe to `global` topic to receive app wide notifications
FirebaseMessaging.getInstance().subscribeToTopic(Config.TOPIC_GLOBAL);
displayFirebaseRegId();
System.out.println("If condition :" + Config.REGISTRATION_COMPLETE + "::" + Config.PUSH_NOTIFICATION);
} else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {
// new push notification is received
String message = intent.getStringExtra("message");
showAlertDialog(MainActivity.this, "Alert", message, true);
txtMessage.setTextColor(Color.GREEN);
Picasso.with(context).load(message).into(iImageView);
// txtMessage.setText(message);
System.out.println("Else condition :" + Config.REGISTRATION_COMPLETE + "::" + Config.PUSH_NOTIFICATION);
}
}
};
This is the code written in main activity, if the app is in the foreground it goes to else if part, if the app is in the background, it does not even enter into onBroadcastReceiver method, then how can I handle background event?
You can use downstream service of FCM
public class FCMMessageHandler extends FirebaseMessagingService {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
String from = remoteMessage.getFrom();
String title = data.get("title");
String content = data.get("content");
// here you need parse a message and ....
}
// Creates notification based on title and body received
private void createNotification(String title, String content, long id, Intent intent) {
Context context = getBaseContext();
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, 0);
android.support.v4.app.NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher).setContentTitle(title)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setContentText(content);
NotificationManager mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify((int) id, mBuilder.build());
}
}
Add to Manifest.xml
<service
android:name=".firebase.FCMMessageHandler"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/common_google_signin_btn_icon_dark" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
Able to handle push notifications foreground and background events , created a method for notification in Service class and in mainactivity added the below code
if (getIntent().getExtras() != null) {
System.out.println("Coming to if method");
String sMessage = getIntent().getStringExtra("message");
String sImageUrl = getIntent().getStringExtra("image");
String sPhoto = getIntent().getStringExtra("photo");
System.out.println("Result :" +sMessage + "::" + sImageUrl + "::" + getIntent().getStringExtra("is_background"));
for (String key : getIntent().getExtras().keySet()) {
String value = getIntent().getExtras().getString(key);
if (key.equals("is_background") && value.equalsIgnoreCase("True")) {
txtMessage.setText("Success :" + sMessage);
Picasso.with(this).load(sPhoto).into(imageView);
}
}
}
You can use
private void generateNotification(Context context, String message) {
int icon = R.mipmap.app_icon;
final int soundResId = R.raw.notification_sound;
try {
Intent intent = new Intent(this, TragetActivityName.class);
intent.putExtra("usedfor", "");
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)
.setSmallIcon(R.mipmap.driver_app_ico)
.setContentTitle("Application name")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager1 = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager1.notify(0 /* ID of notification */, notificationBuilder.build());
} catch (Exception e) {
}
}
So Inorder to change notification icon you add this in your android manifest.
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_stat_ic_notification" />
Change icon form resources.
This is the simplest method to change notification icon.
You can change notification color by adding
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
and follow this answer in Stack Overflow to open particular activity on click of notification. Read fcm documentation Here