简体   繁体   中英

Load Fragment on FCM Push Notification click

I am using pyFCM on a remote server to push event notifications to my app. The notification has a data payload as well, and this is needed for making some UI changes.

When the server app sends the app a notification, there is a notification that pops up on the phone, pressing which causes the default activity to be opened. Also, I have overridden the onMessageReceived in the service extending FirebaseMessagingService, and the data payload is then taken from the message and processed.

I have seen multiple questions on SO like these:

  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

One thing in common with all the above SO questions is that they involve building a notification using Notification.Builder , and then setting up an Activity to open ( or it's onNewIntent to be triggered depending on whether it's android:launchMode is "singleTop" in the Manifest ) . My distinct understanding is that this would work if FCM were used to send the app a data message and not a notification.

The question(s)

What I really fail to understand is how setting up a notification after the data is received from FCM helps me change the behaviour of the notification received from FCM's push. Is that even possible, or have I gotten something wrong?

The second part to this question is: How do I handle a user click on a push notification to load a specific fragment in my activity (when I am not the one creating the fragment in the app - just received via FCM)?

This is the current code that runs in my app.

The onMessageReceived code is :

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

The item handler to handle the data to refresh on the app screen

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

Finally, the function to handle the notification:

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);
    }
  1. You could rather send data messages only instead of sending push messages + payload and receive all notifications in onMessageReceived whether the app is in foreground or background. You can then setup the notification using the setupNotification function you have written and check for extras in the start of the Reviv activity and replace fragments accordingly.
  2. I'm not sure but about this approach using push notifications but here's a suggestion: Try to see if you receive the data payload (check for getIntent().getExtras() ) which you are sending with the push notification in the activity which is opened by default on clicking the push notification.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM