[英]Clicking on notification doesn't open mentioned activity
I am trying to open an Activity
when the notification is clicked and below is my code.我试图在点击通知时打开一个Activity
,下面是我的代码。
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.每当我收到 FCM 的通知时,我都会调用此通知。 The NotificationActivity is not opening whenever I click on notification, rather the app is opening( splash screen->starting activity
of my usual app flow).每当我单击通知时, NotificationActivity都不会打开,而是应用程序正在打开( splash screen->starting activity
我通常的应用程序流程的splash screen->starting activity
)。 Whenever I get notification while the app is already open, the NotificationActivity
is getting opened, but not when app is not already opened.每当我在应用程序已打开时收到通知时, NotificationActivity
就会打开,但在应用程序尚未打开时则不会。 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.注意:请我重申NotificationActivity.class
在应用程序尚未打开状态下单击通知时不会打开。
According to FCM
Documentation, for receiving and handling messages,根据FCM
文档,用于接收和处理消息,
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.要接收消息,请使用扩展 FirebaseMessagingService 的服务。 Your service should override the onMessageReceived callback, which is provided for most message types, with the following exceptions:您的服务应覆盖为大多数消息类型提供的 onMessageReceived 回调,但以下情况除外:
1). 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). 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.在这种情况下,通知被传送到设备的系统托盘,数据有效负载被传送到启动器 Activity 的意图的额外内容中。
So Basically, we have two types of Payloads所以基本上,我们有两种类型的有效载荷
1). 1)。 Notification Payload通知负载
2). 2)。 Data Payload数据负载
3). 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
.您所要做的就是使用任何可以执行HTTP POST Request
工具。 In my case, I am using the Postman tool, a Google Chrome Plugin.就我而言,我使用的是Postman工具,一个 Google Chrome 插件。
Before making a HTTP Post Request
for FCM
, you have to consider three things:在为FCM
发出HTTP Post Request
之前,您必须考虑三件事:
1). 1)。 HTTP Post Request URL : https://fcm.googleapis.com/fcm/send HTTP 发布请求网址: https : //fcm.googleapis.com/fcm/send
2). 2)。 Request Headers :请求头:
i).一)。 Content-Type : application/json内容类型:应用程序/json
ii). ii). Authorization : key = YOUR_SERVER_KEY授权:key = YOUR_SERVER_KEY
Below is the screenshot for the same to show how it looks.下面是相同的屏幕截图,以显示它的外观。
3). 3)。 Body : In this we are going to have JSON
for Notification
and Data Payloads
.正文:在这里,我们将有JSON
用于Notification
和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.在这种情况下, onMessageReceived()
仅在应用程序处于Foreground
时调用,对于所有其他情况,它是System Tray Notification
,单击时会打开Launcher Activity
。 This is helpful when you don't want to control Notifications
by your own and not much data to deal with when Notification
comes.当您不想自己控制Notifications
并且在Notification
到来时没有太多数据需要处理时,这很有用。 You can even control the sound, icon and click_action(only when the app is in Foreground
) without writing any code in your onMessageReceived()
.您甚至可以控制声音、图标和 click_action(仅当应用程序处于Foreground
),而无需在onMessageReceived()
编写任何代码。 One example of a body of such HTTP POST Request
is attached in the screenshot below.下面的屏幕截图中附有此类HTTP POST Request
正文的一个示例。 For opening desired Activity
when sending click_action parameter, you have to use the below code in your onMessageReceived()
.要在发送 click_action 参数时打开所需的Activity
,您必须在onMessageReceived()
使用以下代码。
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (null != remoteMessage.getNotification().getClickAction()) {
startActivity(remoteMessage.getNotification().getClickAction(), null, this);
}
}
and below is your startActivity()
method :下面是你的startActivity()
方法:
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.注意:此click_action
键仅在应用程序处于前台时有效,对于所有其他情况,当应用程序处于后台并关闭时,它不起作用。 It doesn't even open the Launcher Activity, in case of Background and Closed, if this parameter is specified.如果指定了此参数,它甚至不会打开 Launcher Activity,在 Background 和 Closed 的情况下。
GCM
.这与我们在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
.如果我们想自己处理所有Notification
东西,就像我们在GCM
情况下所做的一样,这非常重要。 Example of a body of such HTTP POST Request
is shown below.这种HTTP POST Request
的主体示例如下所示。 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.所以在这种情况下, onMessageReceived()
每次都会被调用,这将与GCM
工作方式相同,对我们所有人都有帮助。 You have to Override
onMessageReceived()
as shown below.您必须Override
onMessageReceived()
,如下所示。
@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.最后但并非最不重要的一点是,我们也可以发送Notification
和Data Payloads
。 In this case, onMessageReceived()
is called when the app is in Foreground
.在这种情况下,当应用程序处于Foreground
时调用onMessageReceived()
。 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
.对于后台和关闭状态, Notification
出现在系统托盘中,类似于Notification Payload
但唯一的区别是我们可以拥有data extras
,当点击Notification
时,我们可以用来将用户重定向到所需的Activity
。 Below is the example of a body of such HTTP POST Request
.Example of a body of such HTTP POST Request
is shown below.下面是这样的主体的示例HTTP POST Request
这样的主体的。实施例HTTP POST Request
被示出如下。 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
.单击系统托盘上的Notification
时,它将打开Launcher Activity
,您需要Override
Launcher Activity
onCreate()
以获取data extras
并将用户重定向到所需的Activity
。 Below is the code, you have to write in onCreate()
of your Activity
to redirect user to the desired Activity
.下面是代码,您必须在Activity
onCreate()
中写入以将用户重定向到所需的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
.这种类型的另一种情况是,当您的Launcher Activity
在manifest
定义为launchMode="true"
并且Notification
到达时,您的Launcher Activity
位于Foreground
。 So when you click on the Notification, you have to Override
the onNewIntent()
method in your Launcher Activity
to open the desired Activity
.因此,当您单击 Notification 时,您必须Override
Launcher Activity
的onNewIntent()
方法以打开所需的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.所以简而言之,我会说使用Data Payload类型很好,因为它提供了更多的灵活性和对Notification
控制,更重要的是因为我们都习惯了GCM
,所以这种类型是我们都喜欢的。
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.所以不确定这些设备有什么问题。
I had the same problem in my app我在我的应用程序中遇到了同样的问题
This link helped me: https://developer.android.com/training/notify-user/navigation此链接对我有帮助: 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然后在 onMessageReceived 方法中使用 TaskStackBuilder 创建挂起的意图
// 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
You can specify any Activity
to be receiver for push notifications:您可以指定任何Activity
作为推送通知的接收者:
<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)此活动的意图过滤器指定将启动哪个活动以响应推送通知( PACKAGE_NAME
是您的 Android 应用程序包)
So you can add this intent filter in your Activity
which you want to open on the click of Push notification.因此,您可以在您想要点击推送通知时打开的Activity
添加此意图过滤器。
You have to use FLAG_UPDATE_CURRENT
in pendingIntent.您必须在FLAG_UPDATE_CURRENT
中使用FLAG_UPDATE_CURRENT
。
PendingIntent pendingIntent = PendingIntent.getActivity(this, notificationId /* Request code */, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
and also pass the same id to notificationManager
并将相同的 id 传递给notificationManager
notificationManager.notify(notificationId /* ID of notification */, notificationBuilder.build());
If you read the firebase docs in detail, there are two types of payloads如果您详细阅读了 firebase 文档,则有两种类型的有效载荷
The data payload triggers the onMessageReceived() callback when app is both foreground and background.当应用程序同时处于前台和后台时,数据负载会触发onMessageReceived()回调。 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.所以,如果你使用数据有效载荷,这个问题应该可以解决。
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);
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.如果您的应用程序在后台,则通知是由没有您的 pendingIntent 操作的 android 系统创建的。因此它不起作用。 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 https://firebase.google.com/docs/notifications/android/console-device#receive_and_handle_messages
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.创建通知后,使用 shell 命令“adb shell dumpsys activity i [your package name]”详细查看您的通知,以确认它确实是您想要的。 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".在使用“adb logcat -v threadtime -b events”重现此事件期间跟踪事件日志。
Post both of these and we might get something useful about what is going wrong under the hood.发布这两篇文章,我们可能会得到一些有用的信息,了解幕后出了什么问题。
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);
I use this in my FirebaseMessagingService:我在 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());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.