2

Im testing the push notification with my app.

when App in the foreground:

Step 1. Received the notification (in system tray). 
     2. now, I'm in some other screen than the home screen.
     3. Actual Problem: On tap on the notification, it is going to the home screen.
     4. Expected: If the app is in the foreground, just I need to cancel on tap of the notification. (No need to swipe.)

when App in background/killed: (Works well)

Step 1. Received the notification (in the system tray)
     2. On tap, open the home screen of the app.

Tried with setting launch mode flags in intent. Not helped. Below is my code. Please suggest the solution guys.

    Intent resultIntent = new Intent(this, MainActivity.class);
    //resultIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    // resultIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);

    PendingIntent resultPendingIntent =
            PendingIntent.getActivity(
                    this,
                    0,
                    resultIntent,
                    PendingIntent.FLAG_UPDATE_CURRENT
            );


    NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(this);

    mBuilder.setContentIntent(resultPendingIntent);
    mBuilder.setSmallIcon(R.mipmap.ic_launcher);
    mBuilder.setContentTitle(title);
    mBuilder.setContentText(body);
    mBuilder.setAutoCancel(true);
    mBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(body));
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        mBuilder.setChannelId(TestUtils.creatChanel(this).getId());
    }

    NotificationManager mNotificationManager =
            (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.notify(642, mBuilder.build());
Dev
  • 119
  • 1
  • 4
  • 13
  • you want to cancel notification always? whats the purpose of cancel when app in foreground? – Ranjithkumar Jun 20 '19 at 05:34
  • No. I don't want to cancel the notification always. The purpose of notification should not affect the app navigations. If im in screen 3 and i tap on notification, it takes me now to home screen. – Dev Jun 20 '19 at 05:41
  • If navigation should not affect app navigation then you have to cancel all your notifications while you are in your app. – Nik Jun 20 '19 at 05:49

4 Answers4

6

Not sure about dismiss notification on tap, but since your concern is wrong navigation.

We can check app is in foreground or not and prevent new activity to be opened from notification click, if app is in foreground.

//If app is in foreground setting pending intent to null
PendingIntent pendingIntent;
        Intent notificationIntent = new Intent(getApplicationContext(), Main2Activity.class);

        if(isAppInForeground()){
            Log.e("--^","inForeground");
            pendingIntent = null;
        }else{
            Log.e("--^","inBackground");
            notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        }

Add this function (SOURCE: link)

private boolean isAppInForeground() {
        ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningAppProcessInfo> services = activityManager.getRunningAppProcesses();
        boolean isActivityFound = false;

        if (services.get(0).processName
                .equalsIgnoreCase(getPackageName()) && services.get(0).importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
            isActivityFound = true;
        }

        return isActivityFound;
    }

In this case if notification came when app is in foreground, it will do nothing if clicked. So user has only one option left to swipe it to remove.

Naitik Soni
  • 700
  • 8
  • 16
  • 1
    This will not work. As per @Samp functionality, if you are in foreground and if you get notification and then if you close application and then tap on that notification then nothing will happen. It will not open Application due to pending intent is null. – Nik Jun 20 '19 at 06:35
  • @Nik yes..in that scenario we need to find out some other solution. thanks – Naitik Soni Jun 20 '19 at 06:38
  • @Nik Yes. You are correct. This solution will affect the background soultions. (At)Naitik Thanks for trying out – Dev Jun 20 '19 at 06:50
  • Is there any way to do with setting Flags with intent which im passing? – Dev Jun 20 '19 at 06:52
  • you can add android:launchMode="singleTop" to MainActivity but then also it will not work if you are not in MainActivity. – Nik Jun 20 '19 at 06:56
  • I suggest you to remove notification while you are in foreground. – Nik Jun 20 '19 at 06:56
  • @Nik Singletop didn't work. Tried. It's a requirement to show notification even in the foreground. I'm just pushing to keep the "Cancel" button in the notification. But again i need to work for cancel btn stuffs – Dev Jun 20 '19 at 07:01
  • 1
    Yes, It is batter idea to put button to Notification using RemoteView. – Nik Jun 20 '19 at 07:03
  • But user can still click on notification instead of buttons. Problem will be still there. – Naitik Soni Jun 20 '19 at 07:06
  • @NaitikSoni Yes. Have to live with that – Dev Jun 20 '19 at 07:16
1

You can create Custom Notification with close button to close notification using RemoteViews

// create Notification with RemoteViews:

RemoteViews remoteViews= new RemoteViews(getApplicationContext().getPackageName(), R.layout.your_custom_notification);
Intent closeIntent = new Intent(context, CloseNotificationService.class);
hangUpIntent.setAction("close");

PendingIntent pendingCloseIntent = PendingIntent.getBroadcast(this, 0, closeNotification, PendingIntent.FLAG_UPDATE_CURRENT);

remoteViews.setOnClickPendingIntent(R.id.cancel_notification, pendingCloseIntent);

// create notification here..
Notification customNotification = new NotificationCompat.Builder(context, CHANNEL_ID)
    .setSmallIcon(R.drawable.notification_icon)
    .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
    .setCustomContentView(remoteViews)
    .build();

OnClick of close button it will redirect to service class:

public class CloseNotificationService extends IntentService {

        /**
         * Creates an IntentService.  Invoked by your subclass's constructor.
         */
        public CloseNotificationService() {
            super("notificationIntentService");
        }

        @Override
        protected void onHandleIntent(@Nullable Intent intent) {
            switch (intent.getAction()) {

                case "close":
                    Handler hangUpHandler = new Handler(Looper.getMainLooper());
                    hangUpHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            NotificationManager notifManager = 
                                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                            notifManager.cancel(notificationId); // get notification id from intent.
                        }
                    });
                    break;
            }
        }
    }

For more information of RemoteViews you can refer official google developer website https://developer.android.com/training/notify-user/custom-notification

Nik
  • 1,991
  • 2
  • 13
  • 30
1

Instead of this:

Intent resultIntent = new Intent(this, MainActivity.class);

do this:

Intent resultIntent = getPackageManager().getLaunchIntentForPackage("your.package.name");

and put that in your Notification. This will launch the app if it is not already running, otherwise it will just bring the app's task to the foreground in whatever state it was when the user last used it. If the user is already in the app (ie: on another screen), this will do nothing when the user clicks the Notification.

Should be exactly what you are looking for.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • @ David : Just now tried. Getting NullpointerException 'boolean android.content.Intent.migrateExtraStreamToClipData()' on a null object reference. I just did what you suggested. any idea on this? – Dev Jun 24 '19 at 00:41
  • This error cant possibly be due to the change I suggested. Look at the stacktrace to see where that error is coming from – David Wasser Jun 24 '19 at 11:15
  • @ David: Actually I didn't try after that. Achieved the same functionality by passing empty intent when the app is in the foreground. Works as per mine requirement. – Dev Jul 03 '19 at 00:37
  • FATAL EXCEPTION: Firebase-MyFirebaseMessagingService java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Intent.migrateExtraStreamToClipData()' on a null object reference at android.app.PendingIntent.getActivity(PendingIntent.java:346) at android.app.PendingIntent.getActivity(PendingIntent.java:309) at my.pkg.MyFirebaseMessagingService.sendNotification(MyFirebaseMessagingService.java:101) . – Dev Jul 03 '19 at 00:45
  • The line in 101 is : Intent resultIntent = getPackageManager().getLaunchIntentForPackage("my.package"); contentIntent = PendingIntent.getActivity(this, INAPP_MESSAGE_REQUEST_ID, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT); – Dev Jul 03 '19 at 00:46
  • It looks like Firebase expects some "extras" in the `Intent` which you are not providing. But this would have crashed in the same way with the code that you had originally. I'm afraid your confusing 2 different problems. Anyway, happy that you've solved it. – David Wasser Jul 03 '19 at 18:06
0

Inside your launcher activity have you tried notification manager class cancelAll() method?? In this way if there is already a notification on launch then it will cancelled automatically

Neha Rathore
  • 429
  • 2
  • 9
  • I need to cancel on tapping of the notification. So the way you mention will not work :( – Dev Jun 20 '19 at 05:30