【问题标题】:Load Fragment on FCM Push Notification click在 FCM 推送通知上加载片段单击
【发布时间】:2019-01-06 05:34:22
【问题描述】:

我在远程服务器上使用 pyFCM 将事件通知推送到我的应用程序。通知也有一个数据负载,这是进行一些 UI 更改所必需的。

当服务器应用向应用发送通知时,手机上会弹出一个通知,按下它会导致打开默认活动。另外,我在扩展 FirebaseMessagingService 的服务中覆盖了 onMessageReceived,然后从消息中获取数据负载并进行处理。

我在 SO 上看到了多个这样的问题:

  1. How to open Fragment on click of push notification
  2. Open fragment from notification when the app in background
  3. How to open fragment page, when pressed a notification in android
  4. Open a fragment when press a notification in android

与上述所有 SO 问题的共同点是,它们涉及使用 Notification.Builder 构建通知,然后设置要打开的 Activity( 或者它是 onNewIntent 被触发取决于它是否是 android:launchMode 是 Manifest 中的 "singleTop" ) 。我的独特理解是,如果使用 FCM 向应用发送数据消息而不是通知,这将起作用。

问题

我真正不明白的是如何在从 FCM 接收到数据之后设置通知帮助我改变从 FCM 的推送接收到的通知的行为。这有可能吗,还是我做错了什么?

这个问题的第二部分是:如何处理用户点击推送通知以在我的活动中加载特定片段(当我不是在应用程序中创建片段的人时 - 刚刚通过 FCM 收到)?

这是在我的应用中运行的当前代码。

onMessageReceived 代码是:

@Override
public void onMessageReceived(RemoteMessage remoteMessagenew) {

    this.remoteMessage = remoteMessagenew;
    super.onMessageReceived (remoteMessage);
    database = MyDatabase.getDatabase(getApplication());
    appuser = database.AppDao().getUserDetails(); 


    Log.d(TAG, "onMessageReceived: ");
    Log.d (TAG, "onMessageReceived: #########################################################");
    Log.d (TAG, "onMessageReceived: #########################################################");
    Log.d (TAG, "onMessageReceived: Message Data is : " + remoteMessage.getData ());


    Map messageData = remoteMessage.getData ();

    // Broadcast
    args = new Bundle ();
    int stage = 0 ;
    Log.d (TAG, "onMessageReceived: ");
    if(messageData.containsKey ("otherid")) {
        incidenthandler(messageData);
    } else  if(messageData.containsKey ("itemid")) {
        itemhandler(messageData);
    }
}

处理要在应用屏幕上刷新的数据的项处理程序

    private void itemhandler(Map messageData) {
    messagebody = remoteMessage.getNotification().getBody();

    if(messageData.containsKey("itemid")) {
        Log.d(TAG, "itemhandler: #######################");
        Log.d(TAG, "itemhandler: #######################");
        Log.d(TAG, "itemhandler: UPDATING");
        Log.d(TAG, "itemhandler: #######################");
        Log.d(TAG, "itemhandler: #######################");

        String item = (String ) messageData.get("itemid");
        JsonParser jsonParser = new JsonParser();
        JsonObject jsonObject = (JsonObject)jsonParser.parse(item);
        item refreshedItem = parseFromJson(jsonObject);
        database.revivDao().upsert(refreshedItem);

    } else {
        // this really shouldn't happen, but putting in a scenario where this does
    // syncing the db with the app
        Log.d(TAG, "itemhandler: #######################");
        Log.d(TAG, "itemhandler: #######################");
        Log.d(TAG, "itemhandler: REFRESHING "); 
        Log.d(TAG, "itemhandler: #######################");
        Log.d(TAG, "itemhandler: #######################");

    // this triggers a call to my intentservice to refresh the db

    Log.d(TAG, "itemhandler: refreshing items");
        Intent intent = new Intent ("refreshitems");
        Bundle clickdata = new Bundle();
        data.putString("item_sub1", item_sub1);
        data.putString("item_sub1", item_sub1);
        intent.putExtra("data", clickdata) ;  // add Bundle to Intent
        localBroadcastManager.getInstance(getApplication()).sendBroadcast(intent); // Broadcast Intent
    }

    String itemid = messageData.get("itemid").toString();
    try{
        Log.d(TAG, "itemhandler: #######################");
        Log.d(TAG, "itemhandler: #######################");
        Log.d(TAG, "itemhandler: sending localbroadcast");
        Log.d(TAG, "itemhandler: #######################");
        Log.d(TAG, "itemhandler: #######################");

    // this is where I try and switch to the screen to display some info - if the app is running

        Intent notificationIntent = new Intent("switchtofragment");
        notificationIntent.putExtra("launchitemfragment", true);
        notificationIntent.putExtra("itemid", itemid);
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        if(localBroadcastManager == null) localBroadcastManager = LocalBroadcastManager.getInstance(getApplication());
        localBroadcastManager.sendBroadcast(notificationIntent);

   // now override the notification to load the fragment on click

        setupNotification(itemid, messagebody);
        notificationManager.notify(1, builder.build());

    } catch (NullPointerException e){
        return;
    }
}

最后是处理通知的函数:

private void setupNotification(String housecallid, String message) {
        //Log.d(TAG, "setting up notification");
        String idChannel = ANDROID_CHANNEL_ID;
        Context context = getApplicationContext();

        Intent notificationIntent = new Intent(getApplicationContext(), Reviv.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        notificationIntent.putExtra("housecallid", housecallid);
        notificationIntent.putExtra("launchhousecallfragment", true);
        Bundle extras = new Bundle();
        extras.putBoolean("launchhousecallfragment", true);
        extras.putString("housecallid", housecallid);
        notificationIntent.putExtras(extras);
        notificationIntent.putExtra("data", extras);


        PendingIntent pendingIntent = PendingIntent.getActivity(this,0, notificationIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        if(notificationManager == null )
            notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);


        builder = new NotificationCompat.Builder(context, null);
        builder. setSmallIcon(R.drawable.heart)
                .setLargeIcon(BitmapFactory.decodeResource(context.getResources(),
                        R.drawable.heart))
                .setContentIntent(pendingIntent)
                .setContentTitle("Reviv")
                .setContentText(message);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if(notificationChannel == null) {
                notificationChannel = new NotificationChannel(idChannel, context.getString(R.string.app_name), importance);
                // Configure the notification channel.
                notificationChannel.setDescription("Reviv Housecall Notification");
                notificationChannel.enableLights(true);
                notificationChannel.setLightColor(Color.RED);
                notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
                notificationManager.createNotificationChannel(notificationChannel);
                builder.setChannelId(idChannel);
                builder.setAutoCancel(true);
            }
        } else {
            builder.setContentTitle(context.getString(R.string.app_name))
                    .setPriority(NotificationCompat.PRIORITY_HIGH)
                    .setColor(ContextCompat.getColor(context, R.color.transparent))
                    .setVibrate(new long[]{100, 250})
                    .setLights(Color.RED, 500, 5000)
                    .setAutoCancel(true);
        }
        builder.setContentIntent(pendingIntent);
    }

【问题讨论】:

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


    【解决方案1】:
    1. 您可以只发送 data 消息,而不是发送推送消息 + 有效负载并在 onMessageReceived 中接收所有通知,无论应用程序是在前台还是后台。然后,您可以使用您编写的 setupNotification 函数设置通知,并在 Reviv 活动的开头检查额外内容并相应地替换片段。
    2. 我不确定这种使用推送通知的方法,但这里有一个建议:尝试查看您是否收到您使用 push 发送的数据负载(检查 getIntent().getExtras())单击推送通知时默认打开的活动中的通知。

    【讨论】:

    • 我也试过这个选项。但是,如果应用程序关闭,通过 FCM 发送的数据消息不会得到处理 - 这意味着应用程序用户将不得不定期检查他们的应用程序,或者一直打开它,这不是一个实际的现实世界场景,并且因此需要推送通知。
    • @kilokahn 他们做到了!我已经在我大学的应用程序中自己实现了它。应用程序是否关闭并不重要。检查您是否确实在发送 data 消息。
    • 很抱歉,我的经验表明并非如此。正如您在文档中看到的,数据消息在 backgrounded 应用程序中触发 onMessageReceived,而不是被杀死/死/关闭的应用程序。您能否指出任何可以告诉我在这种情况下处理数据消息的资源? firebase.google.com/docs/cloud-messaging/android/receive
    • 在您提供的链接的汇总表中可以看到,无论是前台应用还是后台应用,数据消息都是在onMessageReceived中接收的。试试看!!
    • 我已经有了,但它似乎不起作用。打开时发送到我的应用程序的数据消息具有所有预期结果 - 无论是 FG 还是 BG。但是,当应用程序被强制关闭或退出(通过finish/finishAffinity)时,我根本没有收到任何通知。
    猜你喜欢
    • 2020-04-21
    • 1970-01-01
    • 2016-04-07
    • 2017-12-09
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    相关资源
    最近更新 更多