Question

There are lots of reasons why detecting if application is on foreground. for example - as a trigger to GCM/C2DM push notification - lot's of apps would have good reason implementing different behavior when app is foreground and background. Other reason could be - shotting down services consuming precious resources, such as querying servers in background task for instance.

Just to be clear: the definition (as I see it) for background app is:
application which none of it activities are invoked the onStart() method, and did not invoke yet the onStop() method. that's because activity is visible to the user in it life cycle only at that time.

From the other hand -

  • seems like Google don't want application to react to the home button (it's not part of the API)

  • reacting to the onBackPressed() on the "root / main" activity as indicator for leaving Activity certainly not good idea (because lots of users using the home button, and not the back button)

  • there is no method in the API allowing determine if app is foreground (according to my definition..)

if I didn't miss something in the API, and it's really the case - Why there is no why to determine easily if the application is foreground or not????!!!!

what I know I can do to determine if the application is foreground is described in this thread - How to detect when an Android app goes to the background and come back to the foreground

but as @Emil saying - it's requiring special permission, or requiring some tricky logic's which very fast becoming problematic to maintain, and it smells like bad approach (although that's what I'm doing for now, because I don't have better idea...)

my questions basically are:

  • Is there no such API method from good reason?

  • Is taking into account if application is foreground or not is a bad approach?

  • Is there any other way to know if application is foreground or not?

Was it helpful?

Solution 2

With the new Android Architecture Components there is an easy way to know if your app is in the foreground or the background.

Just like with the activity scope lifecycle owner there is a general process lifecycle owner which you can subscribe to and get lifecycle updates.

For example:

Add this code in order to register as a lifecycle observer

ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleListener)

And this code in order to receive the relevant callbacks

@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onApplicationOnStartEvent() {

}

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onApplicationOnStopEvent() {

}

Don't forget to remove the observer once you don't need it

ProcessLifecycleOwner.get().getLifecycle().removeObserver(lifecycleListener);

More information and examples can be found in this excellent article:

https://proandroiddev.com/detecting-when-an-android-app-backgrounds-in-2018-4b5a94977d5c

OTHER TIPS

is taking into account if application is foreground or not is a bad approach?

Taking foreground versus background into account is reasonable.

is there any other way to know if application is foreground or not?

You can roughly divide the scenarios for this into two groups:

  1. Cases where you want to take an action immediately upon a change in the foreground/background status

  2. Cases where some other event occurs (AlarmManager alarm, incoming system broadcast, etc.), and at that point you want to take different actions based upon whether or not you are in the foreground

In the former case, onUserLeaveHint() is your most reliable simple option. I cannot guarantee that it will cover all cases, but it should handle the HOME scenario, for example. You are also welcome to maintain a reference count of started activities in a static data member and try to use it instead.

In the latter case, an ordered broadcast can be useful.

I had the same issue. I want to display push notification when my activity is not in foreground mode. Please go through following code and you will get your answer.

    Context ctx = context.getApplicationContext();

    ActivityManager am = (ActivityManager) context
            .getSystemService(ACTIVITY_SERVICE);

    // get the info from the currently running task
    List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);

    PackageManager pm = this.getPackageManager();

    try {
        /**
         * take fore ground activity name
         */
        ComponentName componentInfo = taskInfo.get(0).topActivity;
        if (printLog == true) {
            Log.d("Home", "CURRENT Activity ::"
                    + taskInfo.get(0).topActivity.getClassName());
            Log.d("Home", "Number Of Activities : "
                    + taskInfo.get(0).numRunning);
            Log.d("Home",
                    "Componenet Info : " + componentInfo.getPackageName());
            Log.d("Home",
                    "Componenet Info : " + componentInfo.getClassName());
        }
        /**
         * All activities name of a package to compare with fore ground
         * activity. if match found, no notification displayed.
         */
        PackageInfo info = pm.getPackageInfo(
                "<PackageName>",
                PackageManager.GET_ACTIVITIES);
        ActivityInfo[] list = info.activities;

        for (int i = 0; i < list.length; i++) {
              Log.d("TAG","Activity : "+list[i].name);
        }

    } catch (NameNotFoundException e) {
        e.printStackTrace();
    }

To use this, you have to take permission in your manifest file.

uses-permission android:name="android.permission.GET_TASKS"

Pardon me if I can't get your question.

If it is necessery for you to know if the app is on backround or foreground from a service that is running on the background(doesnt make sense otherwise), then you can just use binding, that is - bind to it on all your activities onResume, and unbind on all activities onPause. then in your service you can manage not only your application visibility to the user, but also which of the activities are open at any time. it is also leak-proof and more stable then a static variable (which can be cleaned up if necessery) as you are using android's API and relying on the correctness of the android OS code itself.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top