I'm trying to use FCM and the notifications only works when I'm not using the application .
when I send notification from device A to device B , then device B receive the message and "show the notification pop with the default sound" and every thing is good... (this happens when device B is not using the application).
when I send notification from device A to device B , then device B receive the message in the onMessageReceived() method but "does not show the notification pop with the default sound".. (this happens when device B is using the application, I mean when the application is open and is being used).
this is my code
FireIDService.java
public class FireIDService extends FirebaseInstanceIdService {
private final String TAG = "FireIDService";
#Override
public void onTokenRefresh() {
String tkn = FirebaseInstanceId.getInstance().getToken();
Log.d("Not","Token ["+tkn+"]");
sendRegistrationToServer(tkn);
}
private void sendRegistrationToServer(String token) {
saveDeviceToken(token);
}
private void saveDeviceToken(String deviceToken) {
//some code..
if(response.body().getStatus() == 1){
doStuff();
}
//some code...
}
#Override
public void onFailure(Call<SaveDeviceTokenResponse> call, Throwable t) {
//code...
}
});
}
private void doStuff(){
Intent intent = new Intent(this, SplashActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1410 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("FCM Message")
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1410 /* ID of notification */, notificationBuilder.build());
}
}
FireBaseMsgService.java
public class FireBaseMsgService extends FirebaseMessagingService{
private final String TAG = "FireBaseMsgService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "test")
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle(remoteMessage.getNotification().getTitle())
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_background))
.setContentText(remoteMessage.getNotification().getBody())
.setAutoCancel(true)
.setColor(0xffff7700)
.setVibrate(new long[]{100, 100, 100, 100})
.setPriority(Notification.PRIORITY_MAX)
.setSound(defaultSoundUri);
Intent resultIntent = new Intent(this, SplashActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(SplashActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
notificationBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(1, notificationBuilder.build());
}
}
this is what added to the AndroidManifest.xml file
<service android:name=".FireIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
</intent-filter>
</service>
<service android:name=".FireBaseMsgService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
and this is the Notify class to be execute
public class Notify extends AsyncTask<Void,Void,Void>{
private String tkn;
private String title;
private String body;
public Notify(String tkn, String title, String body){
this.tkn = tkn;
this.title = title;
this.body = body;
}
#Override
protected Void doInBackground(Void... voids) {
Log.e("Token: ", tkn);
Log.e("Title: ", title);
Log.e("Body: ", body);
try {
URL url = new URL("https://fcm.googleapis.com/fcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization","key=KEY_HERE");
conn.setRequestProperty("Content-Type", "application/json");
JSONObject json = new JSONObject();
json.put("to", tkn);
JSONObject info = new JSONObject();
info.put("title", title); // Notification title
info.put("body", body); // Notification body
info.put("priority", "high");
info.put("show_in_foreground", "true");
json.put("notification", info);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(json.toString());
wr.flush();
conn.getInputStream();
}
catch (Exception e)
{
Log.d("Error",""+e);
}
return null;
}
}
If you are using android 8.0+. You need to specify channelId for notification.
When your app is in background (as mention in your first case), the push notification is recieved in system notification tray, rather than your FireBaseMsgService, and it is handled automatically by the system by channelId is genreated by system itself.
When your app is in foreground (second case) your FireBaseMsgService is executed and have to create notification channelId
Related
Android able to receive notification when app is in foreground and background but when I kill it causing unable to receive notification.
I'm not sure what part was wrong.
code in AndroidManifest.xml
<service
android:name=".MyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
MyFirebaseMessagingService.java
I don't create MyFirebaseIdService.java for refresh token. I use onNewToken(String mToken) in this class instead.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onNewToken(String mToken) {
super.onNewToken(mToken);
Log.e("NEW_TOKEN",mToken);
}
Here is my onMessageReceived code.
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
Log.d(TAG, "From: " + remoteMessage.getFrom());
RemoteMessage.Notification notification = remoteMessage.getNotification();
Map<String, String> data = remoteMessage.getData();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
sendNotification(notification, data);
}
}
sendNotification code, I attempt make it to receive both data payload and notification payload but it still not work.
#RequiresApi(api = Build.VERSION_CODES.O)
private void sendNotification(RemoteMessage.Notification notification, Map<String, String> data) {
String title;
String body;
if (data != null) {
title = data.get("title");
body = data.get("body");
} else {
title = notification.getTitle();
body = notification.getBody();
}
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
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);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "channel_id")
.setContentTitle(title)
.setContentText(body)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(pendingIntent)
.setLargeIcon(icon)
.setColor(Color.BLUE)
.setSmallIcon(R.mipmap.ic_launcher);
try {
String picture_url = data.get("picture_url");
if (picture_url != null && !"".equals(picture_url)) {
URL url = new URL(picture_url);
Bitmap bigPicture = BitmapFactory.decodeStream(url.openConnection().getInputStream());
notificationBuilder.setStyle(
new NotificationCompat.BigPictureStyle().bigPicture(bigPicture).setSummaryText(notification.getBody())
);
}
} catch (IOException e) {
e.printStackTrace();
}
notificationBuilder.setDefaults(Notification.DEFAULT_VIBRATE);
notificationBuilder.setLights(Color.RED, 1000, 300);
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
create channel code
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
"channel_id", "channel_name", NotificationManager.IMPORTANCE_DEFAULT
);
channel.setDescription("channel description");
channel.setShowBadge(true);
channel.canShowBadge();
channel.enableLights(true);
channel.setLightColor(Color.RED);
channel.enableVibration(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500});
managerCompat.createNotificationChannel(channel);
}
managerCompat.notify(101,notificationBuilder.build());
}
}
You cannot receive notification when killed app for one cause:
Some manufacturers, like HUAWEI, OPPO ecc... make unavailable to push notifications while app is not running, this in order to save your battery life. Of course, important app (WhatsApp, Instagram ecc...) make exception by default. In other hand, there's a way to fix it, every app can get this permission manually via settings->battery (it changes phone by phone).
Now you have to find this permission which affords app to push notifications without running. A tip: when I've tick this one, it doesn't work; I had to unistall app via settings->app, then re-install it again
Hi guys as the title suggests I have a problem regarding Firebase Cloud Messaging, everything works perfectly even when the device does not open the app for a long time, receives notifications perfectly, but the problem occurs when I schedule the daily notification via the console firebase li the first time of sending works and sends the notification to all devices, while the next day at the scheduled time the notification is no longer received and this problem I do not know how to solve it, I have tried everything without any solution, the daily notifications do not are received, can you help me thanks.
#SuppressLint("MissingFirebaseInstanceTokenRefresh")
public class MyFirebaseMessagingService extends FirebaseMessagingService {
/*public static int NOTIFICATION_ID = 1;*/
public static String NOTIFICATION = "notification";
public static String NOTIFICATION_CHANNEL_ID = "com.fourapper.forpaper.channel";
#Override
public void onMessageReceived(#NonNull RemoteMessage remoteMessage) {
generateNotification(remoteMessage.getNotification().getBody(), remoteMessage.getNotification().getTitle());
}
private void generateNotification(String body, String title) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
/*PendingIntent pendingIntent = PendingIntent.getActivities(this, 0 , new Intent[]{intent}, PendingIntent.FLAG_ONE_SHOT);*/
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
/*NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);*/
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
builder.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setSmallIcon(R.drawable.ic_logo_forpapaer)
.setVibrate(new long[]{100, 500})
.setSound(soundUri)
.setContentTitle(title)
.setContentText(body)
.setContentInfo("info")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = null;
if (intent.hasExtra(NOTIFICATION)) {
notification = intent.getParcelableExtra(NOTIFICATION);
}
int notificationId = (int) System.currentTimeMillis();
notificationManager.notify(notificationId, notification);
/*if(NOTIFICATION_ID > 2147483646){
NOTIFICATION_ID = 0;
}*/
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Notification", NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setDescription("Channel");
notificationChannel.setBypassDnd(true);
notificationChannel.enableLights(true);
notificationChannel.setVibrationPattern(new long[]{ 0, 500});
notificationChannel.enableVibration(true);
notificationChannel.setImportance(NotificationManager.IMPORTANCE_HIGH);
notificationManager.createNotificationChannel(notificationChannel);
}
notificationManager.notify(notificationId, builder.build());
}
}
below the token
public class GettingDeviceTokenService extends FirebaseInstanceIdService {
#Override
public void onTokenRefresh() {
String deviceToken = FirebaseInstanceId.getInstance().getToken();
assert deviceToken != null;
Log.d("Device Token", deviceToken);
}
}
Below are the photos of the firebase cloud messaging console for scheduled daily sending at 12:00 AM Recipient Time Zone
sending setting change screen
Actually I'm implementing firebasePushNotification service which is working wihtout any issue . Now when I'm receiving push_notification and my app is in foreground by clicking the notification intent is being passed to the desired activity without any error. But when the app is in background or not opened clicking on the notification is not sending the intent to the desired activity and even it's not showing any error . I tried to refer some questions in SO about adding exported=true option in manifest.xml but it couldn't solve my issue.
Code of NotificationManager Class:
public void displayNotification(String title, String body,String post_owner_username,String post_owner_time,
String notif_commenter_username,String notif_comment_time,String follower_username,String type) {
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(ctx, Constants.CHANNEL_ID)
.setSmallIcon(R.drawable.new_icon)
.setContentTitle(title)
.setContentText(body);
Intent i = new Intent(ctx, ProfileHolder.class);
if (type.equals("likes")) {
Bundle b = new Bundle();
b.putString("post_owner_username", post_owner_username);
b.putString("post_owner_time", post_owner_time);
b.putString("what", "show_notification_post");
i.putExtras(b);
i.putExtra("Open", "starred");
}
else if (type.equals("comments")) {
Bundle b = new Bundle();
b.putString("post_owner_username",post_owner_username);
b.putString("post_owner_time", post_owner_time);
b.putString("notif_commenter_username", notif_commenter_username);
b.putString("notif_comment_time",notif_comment_time);
b.putString("what", "show_notification_post");
i.putExtras(b);
i.putExtra("Open", "starred");
}
else if (type.equals("comment_likes")) {
Bundle b = new Bundle();
b.putString("post_owner_username", post_owner_username);
b.putString("post_owner_time", post_owner_time);
b.putString("notif_commenter_username", notif_commenter_username);
b.putString("notif_comment_time", notif_comment_time);
b.putString("what", "show_notification_post");
i.putExtras(b);
i.putExtra("Open", "starred");
}
else if (type.equals("follow")||type.equals("follow_request")) {
Bundle b = new Bundle();
b.putString("searchUsername", follower_username);
i.putExtras(b);
i.putExtra("Open", "search_profile");
}
// i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(ctx, 0, i, PendingIntent.FLAG_ONE_SHOT);
/*
* Setting the pending intent to notification builder
* */
mBuilder.setContentIntent(pendingIntent);
NotificationManager mNotifyMgr =
(NotificationManager) ctx.getSystemService(NOTIFICATION_SERVICE);
if (mNotifyMgr != null) {
mBuilder.setAutoCancel(true);
mNotifyMgr.notify(1, mBuilder.build());
}
}
If you are using firebase push notification
You need to send a click_action attribute ...to open the desired activity when app is in background.
So try ..
Intent i = new Intent(click_action);
click_action is the intent-filter mapping to the desired activity. click_action is mandatory
instead of the Explicit intent call - explicit intent call in the above case will only work when the app is in foreground..
Here is how I've managed to open specific activity from notification when app is in the background/closed and to pass data through Intent.
Application
public class AppConfig extends Application {
#Override
public void onCreate() {
super.onCreate();
FirebaseApp.initializeApp(this);
}
}
Manifest
<service android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service android:name=".MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<!-- Don't forget to set exported attribute to true -->
<activity android:name=".MainActivity" android:exported="true"/>
MessagingService
public class MyFirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
String body = null;
if(remoteMessage.getNotification() != null) {
body = remoteMessage.getNotification().getBody();
}
String id = null;
// get data that server passed (if it passed any at all)
if(remoteMessage.getData().size() > 0) {
id = remoteMessage.getData().get("id");
}
sendNotification(body, id);
}
private void sendNotification(String messageBody, String id) {
// put data you want to send through intent
Bundle bundle = new Bundle();
bundle.putString("id", id);
// create intent, put data, and
Intent intent = new Intent(this, ActivityLogin.class);
intent.putExtras(bundle);
// IMPORTANT! clearing previous tasks so desired activity will launch
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
// customising the notification
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(getResources().getString(R.string.app_name))
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
How to get full content of notification in Lolipop or above devices.
I am unable to get notification detail like buttons and icons in notification with this.
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
String pack = sbn.getPackageName();
String ticker ="";
if(sbn.getNotification().tickerText !=null) {
ticker = sbn.getNotification().tickerText.toString();
}
Bundle extras = sbn.getNotification().extras;
String title = extras.getString("android.title");
String text = extras.getCharSequence("android.text").toString();
Log.i("Package",pack);
Log.i("Ticker",ticker);
Log.i("Title",title);
Log.i("Text",text);
Intent msgs = new Intent("Msg");
msgs.putExtra("package", pack);
msgs.putExtra("ticker", ticker);
msgs.putExtra("title", title);
msgs.putExtra("text", text);
LocalBroadcastManager.getInstance(context).sendBroadcast(msgs);
}
As I have seen you did not create your notification. You need a notification builder just after your notification is received in your application.
Hence in the receiver of your broadcast, you need to create the notification to be shown in your status bar like the following.
// Inside your broadcast receiver
int notificationID = new Random().nextInt();
Intent intent = new Intent(mContext, YourHomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, notificationID, intent, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(mContext)
.addAction(R.drawable.ic_prev, "BUTTON 1", myIntentToButtonOneScreen)
.addAction(R.drawable.ic_pause, "BUTTON 2", myIntentToButtonTwoScreen) // #1
.addAction(R.drawable.ic_next, "BUTTON 3", myIntentToButtonThreeScreen)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
if (result != null)
notificationBuilder.setLargeIcon(result);
NotificationManager notificationManager =
(NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationID, notificationBuilder.build());
This is just a sample code which might not work. But this is just to give you an idea. Please follow this developer documentation for better understanding.
Update
Based on the comment asking for the notification listener service, here's sample code on how you can listen to notification that was sent to your mobile. Considering you have used Firebase cloud messaging.
public class FCMListenerService extends FirebaseMessagingService {
private FCMNotificationResponse mFcmNotificationResponse;
private RemoteMessage.Notification notification;
private Map data;
private String from;
#Override
public void onMessageReceived(RemoteMessage message) {
parseRemoteMessage(message);
}
private void parseRemoteMessage(RemoteMessage message) {
from = message.getFrom();
data = message.getData();
notification = message.getNotification();
Logger.logD("Message", "From: " + from);
// Check if message contains a data payload.
if (data.size() > 0) {
Logger.logD("Data", "Message data payload: " + data.toString());
setNotificationResponseFromData(data);
}
createNotification(this, notification.getTitle(), notification.getBody(), mFcmNotificationResponse.getIcon());
}
// Here you parse the JSON body received from notification
private void setNotificationResponseFromData(Map data) {
Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(data);
mFcmNotificationResponse = gson.fromJson(jsonElement, FCMNotificationResponse.class);
}
private void createNotification(Context context, String title, String message, String imageUrl) {
new CreateNotificationAsyncTask(context, title,
message, imageUrl).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
onMessageReceived function is called when a notification is received. Then you need to parse your data and then create the notification accordingly.
This class won't to handle multiple GCM messages and show them on notification bar,currently handle only one, how can make it to handle multiple messages?
public class GCMIntentService extends GcmListenerService {
private static final String TAG = "GCMIntentService";
int notifyid = 0;
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
Log.d(TAG, "from:" + from);
Log.d(TAG, "message:" + message);
sendNotification(message);
}
private void sendNotification(String message) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, notifyid, intent, PendingIntent.FLAG_ONE_SHOT);
Uri defaultSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.logo)
.setContentTitle("New Messsage")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSound)
.setContentIntent(pendingIntent);
int numMessages = 0;
notificationBuilder.setContentText(message).setNumber(++numMessages);
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notifyid, notificationBuilder.build());
}
}
}
From the documentation:
public void notify (int id, Notification notification)
Post a notification to be shown in the status bar. If a notification with the same id has already been posted by your application and has not yet been canceled, it will be replaced by the updated information.
notifyid never appears to change in the code you've posted, which is why you only see a single notification.