【问题标题】:Clicking on notification doesn't open mentioned activity单击通知不会打开提及的活动
【发布时间】:2017-03-17 23:02:36
【问题描述】:

单击通知时,我正在尝试打开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 清单:

<?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>

每当我收到来自 FCM 的通知时,我都会调用此通知。每当我点击通知时,NotificationActivity 都不会打开,而是应用正在打开(splash screen-&gt;starting activity 我通常的应用流程)。每当我在应用程序已经打开时收到通知时,NotificationActivity 就会被打开,但在应用程序尚未打开时不会。有人可以帮我解决这个问题吗?

注意:我重申NotificationActivity.class在应用尚未打开状态下点击通知时不会打开。

【问题讨论】:

标签: java android push-notification firebase-cloud-messaging firebase-notifications


【解决方案1】:

您可以指定任何Activity 作为推送通知的接收者:

<intent-filter>
    <action android:name="PACKAGE_NAME.MESSAGE"/>
    <category android:name="android.intent.category.DEFAULT"/>
</intent-filter>

该活动的意图过滤器指定将启动哪个活动以响应推送通知(PACKAGE_NAME 是您的 Android 应用程序包)

因此,您可以在您的 Activity 中添加此意图过滤器,点击推送通知即可打开该过滤器。

【讨论】:

  • 为什么要投反对票?它对我有用。也尝试添加这一行..
  • 这个答案应该更清晰具体的写代码
【解决方案2】:

如果您详细阅读 firebase 文档,则有两种类型的有效负载

  • 数据负载
  • 通知负载

当应用同时处于前台和后台时,数据负载会触发 onMessageReceived() 回调。通知负载不是这种情况,它仅在前台状态触发回调。所以,如果你使用数据负载,这个问题应该可以解决。

【讨论】:

  • 在我的情况下每次都会触发通知。我在打开屏幕时遇到问题,而不是通知触发
  • 尝试在 Intent 中使用 FLAG_ACTIVITY_CLEAR_TOP 标志,在 PendingIntent 中使用 FLAG_CANCEL_CURRENT 标志。
【解决方案3】:

检查此代码并告诉我。

        Intent intent = new Intent(this, LoginActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        pendingIntent = PendingIntent.getActivity(this, 0, intent,
                PendingIntent.FLAG_ONE_SHOT);

【讨论】:

    【解决方案4】:

    您必须在pendingIntent 中使用FLAG_UPDATE_CURRENT

    PendingIntent pendingIntent = PendingIntent.getActivity(this, notificationId /* Request code */, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
    

    并将相同的 id 传递给notificationManager

     notificationManager.notify(notificationId /* ID of notification */, notificationBuilder.build());
    

    【讨论】:

      【解决方案5】:

      这是有意的行为。如果您的应用程序在后台,通知是由没有您的 pendingIntent 操作的 android 系统创建的。所以它不起作用。在前台情况下它可以工作,因为通知是由您的代码创建的。

      请查看以下链接中的文档。 https://firebase.google.com/docs/notifications/android/console-device#receive_and_handle_messages

      【讨论】:

      • 那么,无论应用程序是在前台还是后台,我如何才能通过单击通知来打开预期的活动。现在我的应用程序在后台点击通知时打开。请建议
      • 当服务器通过 gcm 或 fcm 向设备发送通知负载时,您必须添加数据负载,即 "data":{"your_action_key":"action_value_like_activity"} 并从您的 onMessageRecievedmethod 中读取(RemoteMessage remoteMessage) 并通过解析remoteMessage.getData() 创建通知。
      【解决方案6】:

      根据FCM文档,用于接收和处理消息,

      如果您想在您的应用处于 前台,你需要添加一些消息处理逻辑。

      要接收消息,请使用扩展的服务 Firebase 消息服务。您的服务应该覆盖 onMessageReceived 回调,为大多数消息类型提供, 除了以下情况:

      1)。当您的应用程序在后台时发送的通知。在 在这种情况下,通知会发送到设备的系统托盘。 默认情况下,用户点击通知会打开应用启动器。

      2)。具有通知和数据有效负载的消息,均为背景 和前景。在这种情况下,通知将发送到 设备的系统托盘,数据负载在附加组件中交付 启动器 Activity 的意图。

      所以基本上,我们有两种类型的有效载荷

      1).通知负载

      2). 数据负载

      3)。两者(我们可以考虑的其他类型)。

      现在让我们一一讨论这些有效载荷。在此之前,您需要了解如何将这些 Payload 发送到您的应用程序。您所要做的就是使用任何可以执行HTTP POST Request 的工具。就我而言,我使用的是 Postman 工具,一个 Google Chrome 插件。

      在为FCM 制作HTTP Post Request 之前,您必须考虑三件事:

      1)。 HTTP 发布请求 URL: https://fcm.googleapis.com/fcm/send

      2)。请求标头:

      我)。内容类型:应用程序/json

      ii)。授权:key = YOUR_SERVER_KEY

      下面是相同的屏幕截图,以显示它的外观。

      3)。正文:在此我们将有JSON 用于NotificationData Payloads

      • 所以从 Notification Payload 开始,这是最简单的。在这种情况下,onMessageReceived() 仅在应用程序位于 Foreground 时调用,对于所有其他情况,它是 System Tray Notification,单击时会打开 Launcher Activity。当您不想自己控制Notifications 并且当Notification 出现时没有太多数据需要处理时,这很有帮助。您甚至可以控制声音、图标和 click_action(仅当应用程序位于 Foreground 时),而无需在 onMessageReceived() 中编写任何代码。下面的屏幕截图中附有此类HTTP POST Request 正文的一个示例。

      要在发送 click_action 参数时打开所需的Activity,您必须在您的onMessageReceived() 中使用以下代码。

      @Override
      public void onMessageReceived(RemoteMessage remoteMessage) {
          if (null != remoteMessage.getNotification().getClickAction()) {
                  startActivity(remoteMessage.getNotification().getClickAction(), null, this);
          }
      }
      

      以下是您的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);
      }
      

      注意:此click_action 键仅在应用程序处于 前台,适用于应用程序处于后台的所有其他情况,并且 关闭,它不起作用。它甚至没有打开启动器活动, 如果指定了此参数,则在 Background 和 Closed 的情况下。

      • 现在是数据负载。这与我们在GCM 中的类似。如果我们想自己处理所有Notification 的东西,这非常重要,就像我们在GCM 的情况下所做的一样。此类HTTP POST Request 的主体示例如下所示。

      所以在这种情况下,onMessageReceived() 每次都会被调用,这与GCM 的工作方式相同,对我们所有人都有帮助。您必须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());
      }
      
      • 最后但并非最不重要的一点是,我们也可以同时发送NotificationData Payloads。在这种情况下,当应用程序位于Foreground 时,会调用onMessageReceived()。对于后台和关闭状态,Notification 在系统托盘中类似于Notification Payload,但唯一的区别是我们也可以拥有data extras,我们可以使用它来将用户重定向到所需的Activity,点击Notification。以下是此类HTTP POST Request 的主体示例。此类HTTP POST Request 的主体示例如下所示。

      单击系统托盘上的Notification 时,它将打开Launcher Activity,您需要Launcher ActivityOverride onCreate() 以获取data extras 并将用户重定向到所需的@987654380 @。下面是代码,您必须在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
      }
      

      这种类型的另一种情况是,当您的Launcher Activitymanifest 中定义为launchMode="true" 并且当Notification 到达时,您的Launcher ActivityForeground 中。所以当你点击Notification时,你必须在你的Launcher ActivityOverrideonNewIntent()方法来打开想要的Activity。以下是相同的示例代码。

      @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();
          }
      }
      

      简而言之,我会说最好使用 Data Payload 类型,因为它提供了更多的灵活性和对Notification 的控制,更重要的是我们都习惯了GCM ,所以这种类型是我们都喜欢的。

      注意:某些设备在接收通知时遇到问题 背景,因为我在这里发现了一些相同的查询。此外在 当时,我正在调查这些案例,我的华硕手机没有收到 上述任何类型的后台通知。所以 不确定这些设备有什么问题。

      【讨论】:

      • 如前所述,我需要在点击通知时打开活动,而不是在收到的消息中,请建议
      • 解决方案对每种情况的处理方式相同。请再看一遍,让我知道你没有得到什么
      • 请查看更新后的答案,希望这会有所帮助:)
      • 不错的信息。它将帮助其他人节省时间:)
      • 关于fcm.googleapis.com控制台,是否可以区分iOS和Android设备?现在,iOS 开发人员想要发送click_action 来满足他们的目的,但这会破坏 Android 应用程序,因为当应用程序在后台时,单击通知没有任何效果 - 它甚至不会启动应用程序。跨度>
      【解决方案7】:

      很抱歉,我是一个相当新的人,所以没有添加评论。

      你可以做以下两件事来做进一步的调查:

      1. 创建通知后,使用 shell 命令“adb shell dumpsys activity i [your package name]”详细查看您的通知,确认它确实是您想要的。 记得用你自己的包名替换“[your package name]”;

      2. 在您使用“adb logcat -v threadtime -b events”重现此事件期间跟踪事件日志。

      发布这两个,我们可能会得到一些有用的信息来了解幕后问题。

      【讨论】:

        【解决方案8】:

        如下所示设置您的待处理意图

        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);
        

        使用

        将其添加到您的通知中
        .setContentIntent(pendingIntent);
        

        【讨论】:

          【解决方案9】:

          我在 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());
          }
          

          【讨论】:

            【解决方案10】:

            我在我的应用中遇到了同样的问题

            这个链接帮助了我: https://developer.android.com/training/notify-user/navigation

            您需要做的是在 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" />
            

            然后在 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
            

            【讨论】:

            • 谢谢,它成功了。我错过了stackBuilder.getPendingIntent() 这部分。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-09-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多