Reputation: 4715
I am trying to open an Activity
when the notification is clicked and below is my code.
Intent intent = new Intent(this.getApplicationContext(), NotificationActivity.class);
intent.putExtra("msgBody",messageBody);
intent.putExtra(Constants.NOTIF_INTENT_TYPE,Constants.NOTIF_INTENT_TYPE);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|Intent.FLAG_ACTIVITY_SINGLE_TOP
|Intent.FLAG_ACTIVITY_CLEAR_TOP); //Tried with many options here
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 , intent,
PendingIntent.FLAG_CANCEL_CURRENT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.otp_icon)
.setContentTitle("Push MSG")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.com.pushapp">
<uses-sdk
android:minSdkVersion="17"
android:targetSdkVersion="21" />
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".AndroidPushApp"
android:allowBackup="true"
android:icon="@drawable/ic_launcher">
<activity
android:name=".PushSplashScreen"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".MainApplicationScreen"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
<activity
android:name=".StartActivity"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
<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>
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<activity
android:name=".NotificationActivity"
android:exported="true"
android:label="@string/title_activity">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
Whenever I get notification from FCM I am calling this notification. The NotificationActivity is not opening whenever I click on notification, rather the app is opening(splash screen->starting activity
of my usual app flow). Whenever I get notification while the app is already open, the NotificationActivity
is getting opened, but not when app is not already opened. Could someone please help me on resolving this?
Note: Please I am reiterating that NotificationActivity.class
is not getting opened when clicked on notification when app is not already opened state.
Upvotes: 28
Views: 16439
Reputation: 31
I had the same problem in my app
This link helped me: https://developer.android.com/training/notify-user/navigation
What you need to do is define parent activity for your desired activity in Manifest:
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- MainActivity is the parent for ResultActivity -->
<activity
android:name=".ResultActivity"
android:parentActivityName=".MainActivity" />
And then use TaskStackBuilder in onMessageReceived method to create pending intent
// Create an Intent for the activity you want to start
Intent resultIntent = new Intent(this, ResultActivity.class);
// Create the TaskStackBuilder and add the intent, which inflates the back stack
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntentWithParentStack(resultIntent);
// Get the PendingIntent containing the entire back stack
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// then use this pending intent to build your notification
Upvotes: 3
Reputation: 4531
I use this in my FirebaseMessagingService:
/**
* Create and show a simple notification containing the received FCM message.
*
* @param messageBody FCM message body received.
*/
private void sendNotification(String title, String messageBody, String data) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = (NotificationCompat.Builder) new NotificationCompat.Builder(getApplicationContext())
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(this.NOTIFICATION_SERVICE);
notificationManager.notify(id++ /* ID of notification */, notificationBuilder.build());
}
Upvotes: 0
Reputation: 1127
Set your pending intent like below
Intent intent = new Intent(this.getApplicationContext(), NotificationActivity.class);
intent.putExtra("msgBody",messageBody);
intent.putExtra(Constants.NOTIF_INTENT_TYPE,Constants.NOTIF_INTENT_TYPE);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
add it to your notification using
.setContentIntent(pendingIntent);
Upvotes: 0
Reputation: 4091
According to FCM
Documentation, for receiving and handling messages,
If you want to receive notifications when your app is in the foreground, you need to add some message handling logic.
To receive messages, use a service that extends FirebaseMessagingService. Your service should override the onMessageReceived callback, which is provided for most message types, with the following exceptions:
1). Notifications delivered when your app is in the background. In this case, the notification is delivered to the device’s system tray. A user tap on a notification opens the app launcher by default.
2). Messages with both notification and data payload, both background and foreground. In this case, the notification is delivered to the device’s system tray, and the data payload is delivered in the extras of the intent of your launcher Activity.
So Basically, we have two types of Payloads
1). Notification Payload
2). Data Payload
3). Both (an additional type we can consider).
Now let's discuss one by one these payloads. Before that you need to understand how can you send these Payloads to your app. All you have to do is to make use of any tool that can perform HTTP POST Request
. In my case, I am using the Postman tool, a Google Chrome Plugin.
Before making a HTTP Post Request
for FCM
, you have to consider three things:
1). HTTP Post Request URL : https://fcm.googleapis.com/fcm/send
2). Request Headers :
i). Content-Type : application/json
ii). Authorization : key = YOUR_SERVER_KEY
Below is the screenshot for the same to show how it looks.
3). Body : In this we are going to have JSON
for Notification
and Data Payloads
.
onMessageReceived()
is called only when the app is in Foreground
, For all other cases, it's a System Tray Notification
, which opens the Launcher Activity
when clicked. This is helpful when you don't want to control Notifications
by your own and not much data to deal with when Notification
comes. You can even control the sound, icon and click_action(only when the app is in Foreground
) without writing any code in your onMessageReceived()
. One example of a body of such HTTP POST Request
is attached in the screenshot below.For opening desired Activity
when sending click_action parameter, you have to use the below code in your onMessageReceived()
.
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (null != remoteMessage.getNotification().getClickAction()) {
startActivity(remoteMessage.getNotification().getClickAction(), null, this);
}
}
and below is your startActivity()
method :
public void startActivity(String className, Bundle extras, Context context) {
Class cls = null;
try {
cls = Class.forName(className);
} catch (ClassNotFoundException e) {
//means you made a wrong input in firebase console
}
Intent intent = new Intent(context, cls);
if (null != extras) {
intent.putExtras(extras);
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
}
NOTE : This
click_action
key will work only when the app is in Foreground, for all other case when the app is in Background and closed, it doesn't work. It doesn't even open the Launcher Activity, in case of Background and Closed, if this parameter is specified.
GCM
. This is very important if we want to handle all the Notification
stuff by ourselve same as we all were doing in case of GCM
. Example of a body of such HTTP POST Request
is shown below.So in this case, onMessageReceived()
is called everytime and this will work in the same way as that of GCM
, so helpful to all of us. You have to Override
onMessageReceived()
as shown below.
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Map<String, String> data = remoteMessage.getData();
if (null != data && 0 < data.size()) {
if (data.containsKey("custom_key_1")) {
sendNotification(data.get("custom_key_1"));
}
}
}
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, DesiredActivity.class);
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.drawable.ic_stat_ic_notification)
.setContentTitle("FCM Message")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
Notification
and Data Payloads
as well. In this case, onMessageReceived()
is called when the app is in Foreground
. For background and closed state, Notification
comes in the system tray similar to Notification Payload
but the only difference is we can have data extras
as well that we can use to redirect user to a desired Activity
, when clicked on a Notification
. Below is the example of a body of such HTTP POST Request
.Example of a body of such HTTP POST Request
is shown below.When clicking on a Notification
on System Tray, it will open the Launcher Activity
and You need to Override
onCreate()
of your Launcher Activity
to get the data extras
and redirect user to the desired Activity
. Below is the code, you have to write in onCreate()
of your Activity
to redirect user to the desired Activity
.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(getIntent().hasExtra("custom_key_1") && getIntent().getStringExtra("custom_key_1")
.equals("custom_value_1")){
startActivity(new Intent(this, DesiredActivity.class));
finish();
return;
}
// other operations
}
Another case to this type is, when your Launcher Activity
is defined as launchMode="true"
in the manifest
and when the Notification
Arrives, your Launcher Activity
is in the Foreground
. So when you click on the Notification, you have to Override
the onNewIntent()
method in your Launcher Activity
to open the desired Activity
. Below is the sample code for the same.
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (getIntent().hasExtra("custom_key_1") && getIntent().getStringExtra("custom_key_1")
.equals("custom_value_1")) {
startActivity(new Intent(this, DesiredActivity.class));
finish();
}
}
So in short, I would say it's good to go with the Data Payload type as it provides more flexibility and control over the Notification
and more importantly as we all are used to GCM
, so this type is what we all would like to prefer.
Note : Some devices are having issue receiving Notifications in Background as I found some queries over same here. Moreover at the time, I was investigating these cases, my ASUS phone was not receiving notifications in Background for any of the types mentioned above. So not sure what's the issue with these devices.
Upvotes: 31
Reputation: 46
Sorry not to add a comment as I'm a fairly new comer.
You can just do the following two things for further investigating:
After the notification has been created, use shell command "adb shell dumpsys activity i [your package name]" to see your notification in detail, to confirm it is really what you want. Remember to replace "[your package name]" with your own package name;
Tracking the event log during the time you are reproducing this using "adb logcat -v threadtime -b events".
Post both of these and we might get something useful about what is going wrong under the hood.
Upvotes: 0
Reputation: 83
You can specify any Activity
to be receiver for push notifications:
<intent-filter>
<action android:name="PACKAGE_NAME.MESSAGE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
This intent filter for the activity specifies which activity will be launched in response to push notification (PACKAGE_NAME
is your Android app package)
So you can add this intent filter in your Activity
which you want to open on the click of Push notification.
Upvotes: 1
Reputation: 1369
Thats the intented behaviour. If your app is in background, notification is created by android system which does not have your pendingIntent action.So it does not work. In the foreground case it works because notification is created by your code.
Please check the doc in the below link. https://firebase.google.com/docs/notifications/android/console-device#receive_and_handle_messages
Upvotes: 0
Reputation: 3007
You have to use FLAG_UPDATE_CURRENT
in pendingIntent.
PendingIntent pendingIntent = PendingIntent.getActivity(this, notificationId /* Request code */, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
and also pass the same id to notificationManager
notificationManager.notify(notificationId /* ID of notification */, notificationBuilder.build());
Upvotes: 2
Reputation: 1985
Check this code and let me know.
Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Upvotes: 0
Reputation: 393
If you read the firebase docs in detail, there are two types of payloads
The data payload triggers the onMessageReceived() callback when app is both foreground and background. This is not the case with notification payload, which triggers the callback in only foreground state. So, if you use the data payload this problem should be solved.
Upvotes: 0