24

I need to show notification to user only if application is not in foreground. Here is my public class MyFirebaseMessagingService extends

FirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        if(applicationInForeground()) {
            Map<String, String> data = remoteMessage.getData();
            sendNotification(data.get("title"), data.get("detail"));
        }

    }

need to implement applicationInForeground() method

amazingbasil
  • 1,695
  • 3
  • 18
  • 23
  • 1
    take a look at it http://stackoverflow.com/questions/2166961/determining-the-current-foreground-application-from-a-background-task-or-service – Rachit Solanki Dec 23 '16 at 06:01
  • you can use Activity's lifecycle callbacks, and send broadcasts to the service when it goes to BG/FG – Vladyslav Matviienko Dec 23 '16 at 06:10
  • How many activities you are using in Application? – Mayur Raval Dec 23 '16 at 06:20
  • There are two type of message in FCM data-message(for background) and display-message(foreground). You have to use different configuration for both message to receive message in background or foreground. have a look here http://stackoverflow.com/questions/37711082/how-to-handle-notification-when-app-in-background-in-firebase – Praveen Dec 23 '16 at 06:29
  • look at Sam answer: http://stackoverflow.com/questions/3873659/ Github project based on that answer: https://github.com/seguri/GetForegroundActivity – Milon May 09 '17 at 19:12
  • Solution from Google here: https://stackoverflow.com/a/48767617/1269737 – StepanM Feb 13 '18 at 13:13

4 Answers4

27

You can control running app processes from android system service. Try this:

private boolean applicationInForeground() {
    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 == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
        isActivityFound = true;
    }

    return isActivityFound;
}

Good luck.

user2167877
  • 1,676
  • 1
  • 14
  • 15
Batuhan Coşkun
  • 2,961
  • 2
  • 31
  • 48
  • Hello, I'm Android newbie. I'm face same issue but stuck on how to import getPackageName(). Does getPackageName() coming from context? How to access context while I'm at service? – Pewh Gosh Jan 27 '18 at 17:21
  • And my another question, would this code work on Android jellybean until Android oreo? Thank you – Pewh Gosh Jan 27 '18 at 17:24
  • 3
    This function is not working on the Android 7.0 from the Service. – Shajeel Afzal Mar 07 '18 at 13:24
  • 1
    Will be better also check services.get(0).importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND – Dobry Feb 20 '19 at 13:44
22

At Google I/O 2016, I gave a talk where one of the topics was how Firebase detects if your app is in the foreground. You can use ActivityLifecycleCallbacks for that by incrementing a counter for every activity in your app that gets started, then decrementing it for each activity that gets stopped. If the counter is > 1, then your app is in the foreground. The relevant part of the talk can be seen on YouTube here.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
20

You could also try using Android Jetpack lifecycle components.

public class AppFirebaseMessagingService extends FirebaseMessagingService implements LifecycleObserver {

    private boolean isAppInForeground;

    @Override
    public void onCreate() {
        super.onCreate();

        ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        ProcessLifecycleOwner.get().getLifecycle().removeObserver(this);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onForegroundStart() {
        isAppInForeground = true;
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onForegroundStop() {
        isAppInForeground = false;
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        if(isAppInForeground) {
            // do foreground stuff on your activities
        } else {
            // send a notification
        }
    }
}

See here how to import the necessary dependencies, since lifecycle is not part of the standard Android SDK.

bompf
  • 1,374
  • 1
  • 18
  • 24
  • 1
    for using of it implementations of `android.arch.lifecycle:extensions` and `android.arch.lifecycle:compiler` must be added, please add it to your answer – Eugene Babich Apr 01 '19 at 09:21
  • 1
    @ZhebzhikBabich, I added a link to Android documentation. – bompf Apr 01 '19 at 10:25
  • @ekashking, it's [this](https://developer.android.com/reference/androidx/lifecycle/ProcessLifecycleOwner.html) class, make sure you have the correct package imported in your classpath. – bompf Nov 04 '19 at 10:01
  • That's what I guessed. I think the answer should start by mentioning that first. – ekashking Nov 04 '19 at 10:04
  • Well, it's part of the Jetpack support library and adding support libraries is fairly standard for Android development. I will clarify my answer. – bompf Nov 04 '19 at 10:53
4

I just report a Kotlin version of @bompf answer

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage

class AppFirebaseMessagingService : FirebaseMessagingService(), LifecycleObserver {

    private var isAppInForeground = false

    override fun onCreate() {
        super.onCreate()
        ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        ProcessLifecycleOwner.get().lifecycle.removeObserver(this)
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onForegroundStart() {
        isAppInForeground = true
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onForegroundStop() {
        isAppInForeground = false
    }

    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        if (isAppInForeground) {
            // do foreground stuff on your activities
        } else {
            // send a notification
        }
    }
}
Khal91
  • 157
  • 1
  • 8