Clicking on FCM notification opens currently closed activity not targeted activity - android

Here is my code, When my app is running in foreground it opens targeted activity but when app is closed or in background, it doesn't opens targeted activity, please help me to solve this problem
I want that by clicking on notification will open targeted activity even app is running / closed.
public void onMessageReceived(RemoteMessage remoteMessage) {
session = new Session(this);
// if (session.getBscloggedin() || session.getAdploggedin()) {
// Log.d(TAG, "FROM:" + remoteMessage.getFrom());
//Check if the message contains data
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data: " + remoteMessage.getData());
}
//Check if the message contains notification
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Mesage body:" + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getBody());
}
}
/**
* Dispay the notification
* #param body
*/
private void sendNotification(String body) {
//for CS101 announcement notification
if (body.contains("CS101")) {
Intent intent = new Intent(this, CS101noti.class);
intent.putExtra("body", body);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0/*Request code*/, intent, 0);
//Set sound of notifica tion
Uri notificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notifiBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("mine")
.setContentText(body)
.setAutoCancel(true)
.setSound(notificationSound)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /*ID of notification*/, notifiBuilder.build());
}

Request code should be unique.
Generally people share with us example like giving request code 0(zero). I am the one of copy/paste developer sometimes. But recently I faced with error using this line.
PendingIntent.getActivity(myContext, 0, myIntent, 0);
Whenever app receives notification, intent activity receives old data because of requestCode. Here is the documentation about that method.
Returns an existing or new PendingIntent matching the given
parameters.
So second parameter(requestCode) should be unique to intent. If you use same request code for every notification, activity will be receive old data. So your requestCode should be unique.
There is also another solution.Use PendingIntent.FLAG_UPDATE_CURRENT as flag. The doc says that;
If the described PendingIntent already exists, then keep it but
replace its extra data with what is in this new Intent.

onMessageReceived callback is not called when you receive notification messages in background. If you receive this type of message in background, you can only handle that in a launcher activity.
The solution would be to either change the backend so that it sends only data messages and you handle them internally, or write some routing code inside your launcher activity.

use "click_action" attribute from your backend from which you are sending push notifications. in that attribute value, you have to pass the fully qualified class path of activity, which should be opened when you click on that notification.for more reference refer handling firebase push

Intent intent = new Intent(this, CS101noti.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
....

Related

Android notification failing to pass custom data to App via intent packed with PendingIntent

I have an App that responds to Firebase messages, posts a notification on the device, and when the notification is tapped by the user is supposed to relaunch the App with the tidbit of info that came with the Firebase message (it's a single < 20 char String).
// In response to onMessageReceived() in a FirebaseMessagingService object...
// 1. create the intent to bundle with the notification and add custom data
Context appContext = this.getApplicationContext();
Intent intent = new Intent(appContext, MainActivity.class);
intent.putExtra("myData",myData); // myData is a simple string passed from FCM - verified it's correct
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); // per docs/StackOverflow
intent.setAction(Intent.ACTION_VIEW);
// 2. package as a one shot pending intent that is fired when the user taps it in system notification list
int requestCode = (int) System.currentTimeMillis();
PendingIntent pendingIntent =
PendingIntent.getActivity(myActivity, requestCode, intent,
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT); // tried with/without FLAG_UPDATE_CURRENT
// 3. build a notification around launching the intent
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(appContext)
.setSmallIcon(R.drawable.mylogo)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(pendingIntent);
// 4. send notification to the system
NotificationManager notificationManager =
(NotificationManager) appContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify((int) System.currentTimeMillis(), notificationBuilder.build());
The Firebase message is received and the notification is successfully sent to the system notification service. When the user taps the notification, the app is brought to the forground but with the same Intent as was originally passed to the app - ie. without myData bundled with the intent. I've tried retrieve the intent in onResume and onCreate and the results are the same - it's missing the data bunlded with the notification.
// Back in the Main activity
Intent intent = this.getIntent();
String myData = intent.getStringExtra("myData"); // always null
doAction(myData); // fails because myData always null
I've been combing StackOverflow and the net for answers and so far I've tried lots of variations but the results are the same - myData is never forwarded.
I am not sure how you are receiving new Intent. You can try onNewIntent().
Lot of this depends on how you have setup your activity in manifest.
If same instance of the activity is brought to front, new intent will be delivered in onNewIntent().
Hope this helps.

Android FCM notification issue

I am struggling with FCM notifications on Android. The issue is only when the app is closed and not running. I am trying to achieve no click activity I don't want the app to open and I do not want the message to disappear. It works perfectly when the app is open and running. When the app is not open I still get the notification but it is not in multi-line so I can only see the beginning of the notification. Then clicking on the notification makes it disappear. I have spent hours trying to find a solution that works. Here is the code i have so far:
private void sendNotification(String messageBody) {
//Intent intent = new Intent(this, MainActivity.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
//PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
// PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("My Car Wash App")
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentText(messageBody)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setStyle(new NotificationCompat.BigTextStyle().bigText(messageBody))
.setPriority(NotificationCompat.PRIORITY_MAX);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
Any help or suggestions would be greatly appreciated.
EDIT *******
The problem is I asked the question poorly after more research I now realize the code above is only being called when my app is open.
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
//Displaying data in log
//It is optional
Log.i("myStuff", "From: " + remoteMessage.getFrom());
Log.i("myStuff", "Notification Message Body: " + remoteMessage.getNotification().getBody());
//Calling method to generate notification
sendNotification(remoteMessage.getNotification().getBody());
}
onMessageReceived is not called when the app is not in the foreground that is why the notifications are not showing multi-line unless the app is running. There is a lot of information posted on this subject but I still can not seem to figure it out.
Here is my c# server side code
*
var data = new
{
to = deviceId,
notification = new
{
body = msg,
title = "My Car Wash",
icon = "myicon"
},
priority = 10
};
Notifications work perfect on iOS and perfect on Android when the app is running. I just can not get the message to show in multi-line correctly and I am not sure what to do.
*
The notification is getting disappeared when you click on it because you did not add any action when onClick is performed.
To give onClick functionality on notification, you have to use PendingIntent with the target activity. You can also add additional data into it if needed.
Before initializing notificationManager, add this code:
Intent openIntent = new Intent(mContext, TargetActivity.class);
// Falg to clear the stack.
openIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
openIntent, 0);
notificationBuilder.setContentIntent(pendingIntent);
FCM displays my notification the way it wants to when the app is closed. That's ok with me. I just want to make sure the entire notification gets read and not lost. Here is my solution...
When an app user clicks on the notification it opens the app and displays the notification in an alert Dialog.
c# server-side code to send the message
var msg2send = new
{
to = deviceId,
priority = 10,
notification = new
{
body = msg,
title = "Red Hill Car Wash",
icon = "myicon"
},
data = new
{
notice = msg
}
};
And in the onCreate of MainActivity
String notice = "";
try {
notice = getIntent().getStringExtra("notice");
if (notice != null)
{
Log.i("myStuff", notice);
///// DISPLAY NOTIFICATION IN AN ALERT DIAGLOG all good!
}
}
catch (Exception ex) {
Log.i("myStuff", ex.getMessage());
}
FCM passes the message to my MainActivity, if a message exists then I grab it and can display it how ever I want. Thank for the comments and input to help solve this issue.
One way is to use data instead of notification to get onMessageReceived() callback both in app foreground or background. The json part is:
{
"data": {
"title": "notification_title",
"body": "notification_body"
},
"to" : "jh578_gsh....jhHGFJ76FH"
}
For detail, follow this link: https://stackoverflow.com/a/37845174/5829624
Edit:
Method 2:
Use a click_action payload in your notification payload. In json:
{
"notification": {
"click_action": "OPEN_ACTIVITY_1",
},
}
And add this intent filter in the Activity (which you want to load when you tap on the notification) in your Manifest:
<intent-filter>
<action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Hope this one will solve your problem.
When application in background "OnMessageReceived" overridden method wont get called in general scenario.
If you want to make "OnMessageReceived" method to call all the time. Ask your web service team to send only "DATA" payload. Dont use "Notify" or "Notification" payload.
If "DATA" payload is send properly from backend then Android application will work on "OnMessageReceived" with a List of Data from RemoteMessage.getDATA();
I struggled the same issue for nearly 2 days and finally got the above solution.

No title in Amazon SNS GCM push notification

I am using Amazon SNS console to send android mobile push notification. I did receive push notification but only the body message is displayed, the title is not displayed.Also when the notification was touched the app was not opened. I am using Amazon AWS SDK for Unity.
It would be great if you share some code, but as i understand you want to receive push with title and body message, so you have to retrieve it first.
When you receive push intent in your Service you should call intent.getExtras().getString("title"). And if you want to open app when you click on push notif you should set it up in your notification Intent.
Here is a simple example how to do it:
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty() && messageType != null) {
switch (messageType) {
case GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR:
Toast.makeText(this, GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR, Toast.LENGTH_SHORT).show();
break;
case GoogleCloudMessaging.MESSAGE_TYPE_DELETED:
Toast.makeText(this, GoogleCloudMessaging.MESSAGE_TYPE_DELETED, Toast.LENGTH_SHORT).show();
break;
case GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE: // retrieve your data here
Log.d("onHandleIntent", "Message= " + extras.getString("message"));
Log.d("onHandleIntent", "Title= " + extras.getString("title"));
sendNotification(extras.getString(message), extras.getString(title));
}
}
PushBroadcastReceiver.completeWakefulIntent(intent);
}
private void sendNotification(String msg, String title) {
NotificationManager mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(this, MainActivity.class); // activity wich you want to open when click on push notification
notificationIntent.putExtra(NOTIFICATION_TAG, msg);
notificationIntent.putExtra(NOTIFICATION_TITLE_TAG, title);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notifications)
.setContentTitle(title)
.setAutoCancel(true)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
As #Jarik said you would have to do that.
Also assuming youre facing the same problem i did, create a jar file whose class extends the gcm listener or whatever class the callbacks work with(dont remember the name right now, open their class file and you will find the java classes extending the gcm receivers), and then use intent for the notification touch that would open the application. Also this would let you use the title functionality. I found that somehow in amazon sns sdk class files, they have overwritten the title with a "" hence the title always seem to be blank.
Dont forget to put UnityPlayerProxyActivity in the Android manifest.

Get unseen android notifications

I have a service that shows a notification PendingIntent each time it receives a new GCM message. The problem is that the GCM messages can be of different kinds. And if many notifications leave unread, I want not to show them separately but in groups like:
you have 3 unread messages of type A
you have 2 unread messages of type B
you have 4 unread messages of type C
As far as I understand, to get this effect I need to have an access to unread/unseen notifications. Each time when I new notification comes I can check, if there is another unread message of this type, and then decide, whether I create a new notification or update an old one.
My question is: is there a way to see, which notifications are unseen and get access to them?
For any case this is my method to create a message; if an argument notificationId is 0 a new notification should be created. Else - updated.
private int sendNotification(String msg, Integer notificationId) {
Log.d(TAG, "sending message with text: "+msg);
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Random random = new Random();
int notification_id = notificationId==0?random.nextInt(9999 - 1000) + 1000:notificationId;
RemoteViews remoteViews = new RemoteViews(getPackageName(),
R.layout.notification);
Intent intent = new Intent(this, MainActivity.class);
// Send data to NotificationView Class
intent.putExtra("text", msg);
PendingIntent pending= PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("escos")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(pending);
mBuilder.setContent(remoteViews);
remoteViews.setTextViewText(R.id.notiftext, msg);
remoteViews.setImageViewResource(R.id.notifim, R.drawable.ic_launcher);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mNotificationManager.notify(notification_id, notification);
return notification_id;
}
For different Notification strip (A, B, C etc.) in your status bar, use different NOTIFICATION_ID for building the Notification on basis of your defined type or collapse_key received from GCM.
For determining unread and read messages, use a local variable (counter) in Shared Preferences and increment it each time a specific type of Notification comes (on basis of defined type or collapse_key).
Then generate the Notification with that particular NOTIFICATION_ID as Notification with particular NOTIFICATION_ID can override each other. So You can override the previous Notification with Iterative Numbered text in New Notification.
As soon as user click on any Notification or particular Notification, clear the notification and reset the value of (counter) in Shared Preferences.
Edit1 : When you click on Notification with particular Pending Intent, then in that Activity use this code for removing all the Notifications generated from your app :
NotificationManager nMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
try {
nMgr.cancelAll();
} catch (Exception e) {
e.printStackTrace();
}
Note : Do remember to add Try-Catch before you call cancelAll() as cancelAll() may not be supported by the device model and will generate
java.lang.SecurityException: Permission Denial
error.
Edit 2:
You can also use nMgr.cancel(NOTIFICATION_ID); to clear a specific notification, pass NOTIFICATION_ID to particular intent via extras and get the extras in that activity to cancel a particular notification.
And as you click on any notification it will be cleared from status bar unless you have not set .setAutoCancel(false) in your Notification Builder.

Android notification PendingIntent open activity per notification click

I'm currently doing some notifications for my app. Now I've successfully created a notification but problem is that each of my notification doesn't pass different extras on click.
Well what happen is that I only have a loop that calls the createNotification method per loop and also I assign different ID's for those for the notification to appear in different stack.
here's my code:
private void createNotification(String record_name, String file_path, String status, int id) {
/*must pass:
* record_name, (get the record name in DB using the id create a new query method)
* record_status, (simple part just match if equivalent to ready to download for the JSON data then show notif if true)
* record_path *full path* (this one can be get using the record name itself add the path and extension name)*/
/*this will jump from the current activity into the target activity class just do some workarounds here*/
Intent intent = new Intent(this, RecordEditActivity.class);
intent.putExtra("record_name", record_name);
intent.putExtra("record_path", file_path);
intent.putExtra("record_status", status);
PendingIntent pIntent = PendingIntent.getActivity(this,0, intent, 0);
/*build the notification here this is only supported for API 11. Since we've targeted API 11 there will be no problem on this*/
NotificationCompat.Builder notify = new NotificationCompat.Builder(this)
.setContentTitle(record_name + " is ready for download")
.setContentText("Click to view or download recording")
.setAutoCancel(true)
.setSmallIcon(R.drawable.notif_icon)
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.drawable.ic_launcher))
.setTicker("Echo: your file is ready for download")
.setContentIntent(pIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if(Build.VERSION.SDK_INT<16){
/*build notification for HoneyComb to ICS*/
notificationManager.notify(id, notify.getNotification());
}if(Build.VERSION.SDK_INT>15){
/*Notification for Jellybean and above*/
notificationManager.notify(id, notify.build());
}
}
I think the problem is in the PendingIntent part since I don't know which flags should I use for this but I'm not that sure about it.
Got it! what needed is for me to assign an ID for my pendingIntent requestCode what I did is assign the same ID I used for my notificationManager.
More info here.
Just use this one line of code-
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
And for more detail see this answer:
GCM android Push Notification shows old message always. Intent received incorrect

Categories

Resources