375

By background, I mean none of the application's activities are currently visible to the user?

tshepang
  • 12,111
  • 21
  • 91
  • 136
cppdev
  • 6,833
  • 13
  • 40
  • 45
  • 3
    possible duplicate of [How to determine if one of my activities is in the foreground](http://stackoverflow.com/questions/2314969/how-to-determine-if-one-of-my-activities-is-in-the-foreground) – Phrogz Oct 10 '11 at 16:08
  • 11
    I'm confused here.. why can't android provide a simple override on the application class for this? Is it too difficult to know this at the platform level? @Override protected void onApplicationSentToBackground() { } – Chuck D Apr 12 '13 at 02:35
  • 2
    @ChuckD - that would make sense, which is what the Android SDK seems to like to avoid doing at times. :/ – Mark Apr 30 '15 at 23:56
  • http://codingaffairs.blogspot.com/2016/05/check-if-your-android-app-is-in.html – Developine May 25 '16 at 03:40
  • 2
    iOS has this in spades, not sure why Google makes this so hard. It's such an obvious need. – Jerry Destremps Jun 23 '16 at 19:59
  • For me what worked was an alternative implementation. Having one activity and the rest of the UI as fragments. Then the `OnPause` and `OnResume` callbacks can work – pnavk Aug 16 '16 at 02:38
  • Go at @user1269737 answer. That should be the correct answer! – JaviOverflow Jul 01 '18 at 18:15
  • Most recent/correct solution still far down: https://stackoverflow.com/a/48767617/1680919 – Levite Dec 11 '18 at 08:54
  • Although it works there is no need to implement this yourself, google already added ProcessLifecycleOwner doing the same thing for you using LifecycleObserver. Check http://www.stackoverflow.com/a/52678290/6600000 – Keivan Esbati Feb 12 '19 at 13:18
  • [ProcessLifecycleOwner](https://stackoverflow.com/a/54684819/6017001) is the newest solution – S.R Feb 14 '19 at 07:10

37 Answers37

399

There are few ways to detect whether your application is running in the background, but only one of them is completely reliable:

  1. The right solution (credits go to Dan, CommonsWare and NeTeInStEiN)
    Track visibility of your application by yourself using Activity.onPause, Activity.onResume methods. Store "visibility" status in some other class. Good choices are your own implementation of the Application or a Service (there are also a few variations of this solution if you'd like to check activity visibility from the service).
     
    Example
    Implement custom Application class (note the isActivityVisible() static method):

    public class MyApplication extends Application {
    
      public static boolean isActivityVisible() {
        return activityVisible;
      }  
    
      public static void activityResumed() {
        activityVisible = true;
      }
    
      public static void activityPaused() {
        activityVisible = false;
      }
    
      private static boolean activityVisible;
    }
    

    Register your application class in AndroidManifest.xml:

    <application
        android:name="your.app.package.MyApplication"
        android:icon="@drawable/icon"
        android:label="@string/app_name" >
    

    Add onPause and onResume to every Activity in the project (you may create a common ancestor for your Activities if you'd like to, but if your activity is already extended from MapActivity/ListActivity etc. you still need to write the following by hand):

    @Override
    protected void onResume() {
      super.onResume();
      MyApplication.activityResumed();
    }
    
    @Override
    protected void onPause() {
      super.onPause();
      MyApplication.activityPaused();
    }
    

     
    Update
    ActivityLifecycleCallbacks were added in API level 14 (Android 4.0). You can use them to track whether an activity of your application is currently visible to the user. Check Cornstalks' answer below for the details.

  2. The wrong one
    I used to suggest the following solution:

    You can detect currently foreground/background application with ActivityManager.getRunningAppProcesses() which returns a list of RunningAppProcessInfo records. To determine if your application is on the foreground check RunningAppProcessInfo.importance field for equality to RunningAppProcessInfo.IMPORTANCE_FOREGROUND while RunningAppProcessInfo.processName is equal to your application package name.

    Also if you call ActivityManager.getRunningAppProcesses() from your application UI thread it will return importance IMPORTANCE_FOREGROUND for your task no matter whether it is actually in the foreground or not. Call it in the background thread (for example via AsyncTask) and it will return correct results.

    While this solution may work (and it indeed works most of the time) I strongly recommend to refrain from using it. And here's why. As Dianne Hackborn wrote:

    These APIs are not there for applications to base their UI flow on, but to do things like show the user the running apps, or a task manager, or such.

    Yes there is a list kept in memory for these things. However, it is off in another process, managed by threads running separately from yours, and not something you can count on (a) seeing in time to make the correct decision or (b) have a consistent picture by the time you return. Plus the decision about what the "next" activity to go to is always done at the point where the switch is to happen, and it is not until that exact point (where the activity state is briefly locked down to do the switch) that we actually know for sure what the next thing will be.

    And the implementation and global behavior here is not guaranteed to remain the same in the future.

    I wish I had read this before I posted an answer on the SO, but hopefully it's not too late to admit my error.

  3. Another wrong solution
    Droid-Fu library mentioned in one of the answers uses ActivityManager.getRunningTasks for its isApplicationBroughtToBackground method. See Dianne's comment above and don't use that method either.

Community
  • 1
  • 1
Volo
  • 28,673
  • 12
  • 97
  • 125
  • 4
    To know if you pressed the home button or some other app has gained the focus: 1) implement the _good solution_. 2) In ````OnStop```` request to ````isActivityVisible````. – Brais Gabin Oct 08 '12 at 11:10
  • 30
    Unfortunately your 'correct' solution does not work for me. Consider you cycle through activities within your app. What happens then is that your 'inForeground' flag goes like this: True, False(Between 1st activity's onPause and 2nd activity's onResume) then True again, etc. You would then need a hysteresis of some sort. – Radu Dec 05 '12 at 09:11
  • 16
    This solution doesn't work if you can't directly control all the activities. For instance if you have an Activity from a 3rd party sdk or even launch an ACTION_VIEW intent. – user123321 Jan 11 '13 at 21:45
  • @Brais-Gabin +1 for Excellent idea, except that pre-Honeycomb onStop isn't guaranteed to be called so this approach isn't reliable enough for critical features (e.g. security). :( – John Lehmann Feb 07 '13 at 20:52
  • 79
    Android is such a freaking wreck. No one thought that someone might want to persist app level data? Give me a break –  Mar 05 '13 at 20:09
  • A hassle free solution would be to implement option 2 in a new thread or async task as noted. If run on main thread its results are wrong. – Ajibola Mar 15 '13 at 09:02
  • +1 This is the way to go. If you want to know if the app is in a background state (means that the app is closed) just use "onStop()" instead of "onPause()". Great job guys. – Ivan Carosati Nov 16 '13 at 04:30
  • 1
    Careful using onStop(). When switching activities in my app, it appears that the onResume() of the new Activity gets called *before* the onStop() of the previous activity. This would mean that isActivityVisible() would always return after the first activity. Bummer. :/ – SilithCrowe Jan 13 '14 at 22:52
  • @idolon Why when I access static field from BroadcastReceiver is always false? How can i know if is visible from BrowadcastReceiver? – pgarriga Dec 12 '14 at 13:45
  • I use such flags as in your "correct implementation", but as a static variable in `Application` or in a `SharedPreference` to give it a global context. – shkschneider Dec 17 '14 at 15:16
  • 11
    Looks like the real answer to this question is "You cannot check it properly". The so called 'correct' solution is a workaround at best, so is using ActivityLifecycleCallbacks. You still need to consider switching between activities which would be registered as "not in foreground". It blows my mind that you cannot check a simple thing like that... – serine Jan 12 '15 at 19:47
  • 2
    Agreed with _serine_ that this is **not** a foolproof solution. One scenario is if the user pulled down the notification panel, then neither the `onPause`, `onStop`, nor the `onResume` event is called. So what do you do then if none of these events are fired?! –  Jul 09 '15 at 15:51
  • 1
    Instead of using a `boolean`, synchronize on an `int` that you can increment/decrement for the number of times `onPause`/`onResume` are called. In `onPause` -1 ... in `onResume` +1 as long as you're at `0` or greater your app is visible. – Bron Davies Jul 30 '15 at 02:57
  • 1
    None of these solutions are right. For instance, when an application runs if a screen is turned off. Or when an activity appears by timer and a screen is off. In this case onPause is called. Also, a problem may occur when a dialog appears. Probably it should test a moment of pressing Home button. – CoolMind May 10 '16 at 15:52
  • @Idolon Please consider including an option described in my answer http://stackoverflow.com/a/39589149/64605 I know that it is not perfect, but it is simpler that others and does not require special permissions or deprecated code. Frankly once I discovered this method I was very surprised noone mentioned it in this thread, so I think it needs more visibility. – Juozas Kontvainis Sep 20 '16 at 08:33
  • Can i check third party application Like any third party app is working in backgroud or not – Bhanu Sharma Sep 22 '16 at 07:43
  • I think you must mark `MyApplication.activityVisible` `volatile` – Peter Chaula Nov 23 '16 at 16:18
  • Case: As a library, you want to unregister your sensorlistener when the activity of a project, which imported you, is on background. Solution: Not approved since you can't control activities. – Burak Day Jan 05 '18 at 10:57
  • I made this utility class that solves this issue without any special permissions or API level restrictions https://gist.github.com/pantos27/6faad313ba364c947e2487e80aa25c86 – pantos27 Jul 19 '18 at 20:13
  • That's why I choose iPhone... I'm kidding because they have the same issue on iOS. – Dmitry Sep 07 '18 at 06:20
  • Although this is a right answer there is no need to implement this yourself, google already added ProcessLifecycleOwner doing the same thing for you using LifecycleObserver. Check https://stackoverflow.com/a/52678290/6600000 – Keivan Esbati Oct 06 '18 at 10:53
  • The right solution is only a solution if you have only one activity, otherwise you will have a mess. – Offler Dec 11 '19 at 15:47
  • Your "right" solution is wrong according to androids definition... According to https://developer.android.com/guide/background#definition an app is considered to be on foreground in case it has a foreground service running. your "right" doesn't check for it – Rafael Lima Oct 09 '21 at 00:55
  • I guess all "solutions" here are wrong, the main concern that leads one to check if the app is on foreground is the exception android throws when we try to start a service and app is in background (absurd). So, the RIGHT solution is to have a check that is IDENTICAL to the check android will do prior to throw this exception so any approach that consider storing it in a class field might work but is absolutely not fail proof since android doesn't really care about it – Rafael Lima Oct 09 '21 at 00:58
  • @Radu I agree with your point about hysteresis. I think best solution is using ProcessLifecycleOwner that provides lifecycle for the whole application process. Check my answer here: https://stackoverflow.com/a/76002739/8956093 – Ramakrishna Joshi Apr 13 '23 at 07:51
320

GOOGLE SOLUTION - not a hack, like previous solutions. Use ProcessLifecycleOwner

Kotlin:

class ArchLifecycleApp : Application(), LifecycleObserver {

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

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onAppBackgrounded() {
        //App in background
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onAppForegrounded() {
        // App in foreground
    }

}


Java:

public class ArchLifecycleApp extends Application implements LifecycleObserver {

    @Override
    public void onCreate() {
        super.onCreate();
        ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public void onAppBackgrounded() {
        //App in background
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onAppForegrounded() {
        // App in foreground
    }
}

in app.gradle

dependencies {
    ...
    implementation "android.arch.lifecycle:extensions:1.1.0"

    //New Android X dependency is this - 
    implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
    
}

allprojects {
    repositories {
        ...
        google()
        jcenter()
        maven { url 'https://maven.google.com' }
    }
}

You can read more about Lifecycle related architecture components here - https://developer.android.com/topic/libraries/architecture/lifecycle

Ben Butterworth
  • 22,056
  • 10
  • 114
  • 167
StepanM
  • 4,222
  • 1
  • 21
  • 25
  • 14
    This should definitely be the correct answer! It worked like a charm :D – JaviOverflow Jul 01 '18 at 18:13
  • 4
    This works perfectly, I also modified a bit so I could access the foreground/background state more easily outside this class: `companion object { private var foreground = false fun isForeground() : Boolean { return foreground } }` then you can get the foreground state with `ArchLifecycleApp.isForeground()` – Jose Jet Jul 10 '18 at 09:28
  • 7
    Oh man, this is so much better than my old answer. Have a +1 from me. I updated my answer to point people to yours. – Cornstalks Sep 08 '18 at 03:24
  • 5
    Although this is a right answer there is no need to implement callbacks, you can just query ProcessLifecycleOwner whenever you want. Check https://stackoverflow.com/a/52678290/6600000 – Keivan Esbati Oct 06 '18 at 10:54
  • Great Solution, Better than every answers given here... Works Perfectly... – Gaurav Balbhadra Oct 30 '18 at 08:58
  • 7
    As doc says `The LifecycleOwner for the whole application process. Note that if your application has multiple processes, this provider does not know about other processes.` , this is not working for `multiple processes` apps, is there some api we can achieve elegantly? – Kevin Apr 10 '19 at 08:32
  • what will be the result of closing application completely ? This means nothing in foreground and nothing in background – Evgeniy Mishustin Jul 04 '19 at 13:38
  • Sorry, but where is the androix version of ProcessLifecycleOwner? Here is documented: https://developer.android.com/reference/androidx/lifecycle/ProcessLifecycleOwner.html but I cannot find it importing neither androidx.lifecycle:lifecycle-runtime nor androidx.lifecycle:lifecycle-extensions – ARLabs Jul 06 '19 at 13:18
  • @ARLabs, implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'. – CoolMind Aug 30 '19 at 09:20
  • More upvotes on this please, the many answers and topics about this are confusing, meanwhile this is the simplest and best solution... Also the @JoseJet addition is perfect, thanks! – mrj Sep 17 '19 at 14:23
  • 1
    I don't see how this solution can possibly give me an answer on a simple question within an IF statement on my activity (or fragment) whether my app is on the background or foreground. Where is the "IF" statement ??? – ekashking Nov 11 '19 at 21:18
  • Can I use this code to check if another application is running in the background from my application? – Rajat Sangrame Dec 02 '19 at 07:40
  • don't forget adding the class which extends Application to the manifest under the application tag like this: android:name=".ArchLifecycleApp" – Oluwasegun Wahaab Feb 16 '20 at 13:52
  • 1
    But I think this is not a proper solution yet. because, every time I navigate to another activity `onAppBackgrounded()` is calling every time for the current activity and get the `onAppForegrounded()` for the next activity I am navigating to. If anyone know the solution please share. Thanks – A S M Sayem Mar 04 '20 at 06:43
  • 1
    @acntwww did you find a solution for multi-process applications? I need it to work for activities in a separate process. – CamHart Jul 14 '20 at 21:45
  • It worked fine, BUT DO NOT FORGET ADD THIS LINE TO: manifests (inside application tag): '' – Eng.OsamaYousef Sep 27 '20 at 10:03
  • Does not work when you kill the app and receive a notification. It will trigger `ON_START` marking the app state as FOREGROUND while it is not. https://stackoverflow.com/a/52678290/3114632 -> this one fixes the problem. – JakubW Sep 13 '21 at 15:31
  • 4
    The @OnLifecycleEvent annotation is deprecated. It is recommended to use DefaultLifecycleObserver or LifecycleEventObserver instead. Source: https://developer.android.com/reference/androidx/lifecycle/OnLifecycleEvent – lubrum Feb 09 '22 at 17:55
  • 1
    Also, jCenter is deprecated. – lubrum Feb 09 '22 at 18:04
268

DO NOT USE THIS ANSWER

user1269737's answer is the proper (Google/Android approved) way to do this. Go read their answer and give them a +1.

I'll leave my original answer here for posterity's sake. This was the best available back in 2012, but now Android has proper support for this.

Original answer

The key is using ActivityLifecycleCallbacks (note that this requires Android API level 14 (Android 4.0)). Just check if the number of stopped activities is equal to the number of started activities. If they're equal, your application is being backgrounded. If there are more started activities, your application is still visible. If there are more resumed than paused activities, your application is not only visible, but it's also in the foreground. There are 3 main states that your activity can be in, then: visible and in the foreground, visible but not in the foreground, and not visible and not in the foreground (i.e. in the background).

The really nice thing about this method is that it doesn't have the asynchronous issues getRunningTasks() does, but you also don't have to modify every Activity in your application to set/unset something in onResumed()/onPaused(). It's just a few lines of code that's self contained, and it works throughout your whole application. Plus, there are no funky permissions required either.

MyLifecycleHandler.java:

public class MyLifecycleHandler implements ActivityLifecycleCallbacks {
    // I use four separate variables here. You can, of course, just use two and
    // increment/decrement them instead of using four and incrementing them all.
    private int resumed;
    private int paused;
    private int started;
    private int stopped;

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
    }

    @Override
    public void onActivityResumed(Activity activity) {
        ++resumed;
    }

    @Override
    public void onActivityPaused(Activity activity) {
        ++paused;
        android.util.Log.w("test", "application is in foreground: " + (resumed > paused));
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }

    @Override
    public void onActivityStarted(Activity activity) {
        ++started;
    }

    @Override
    public void onActivityStopped(Activity activity) {
        ++stopped;
        android.util.Log.w("test", "application is visible: " + (started > stopped));
    }

    // If you want a static function you can use to check if your application is
    // foreground/background, you can use the following:
    /*
    // Replace the four variables above with these four
    private static int resumed;
    private static int paused;
    private static int started;
    private static int stopped;

    // And these two public static functions
    public static boolean isApplicationVisible() {
        return started > stopped;
    }

    public static boolean isApplicationInForeground() {
        return resumed > paused;
    }
    */
}

MyApplication.java:

// Don't forget to add it to your manifest by doing
// <application android:name="your.package.MyApplication" ...
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        // Simply add the handler, and that's it! No need to add any code
        // to every activity. Everything is contained in MyLifecycleHandler
        // with just a few lines of code. Now *that's* nice.
        registerActivityLifecycleCallbacks(new MyLifecycleHandler());
    }
}

@Mewzer has asked some good questions about this method that I'd like to respond to in this answer for everyone:

onStop() is not called in low memory situations; is that a problem here?

No. The docs for onStop() say:

Note that this method may never be called, in low memory situations where the system does not have enough memory to keep your activity's process running after its onPause() method is called.

The key here is "keep your activity's process running..." If this low memory situation is ever reached, your process is actually killed (not just your activity). This means that this method of checking for backgrounded-ness is still valid because a) you can't check for backgrounding anyway if your process is killed, and b) if your process starts again (because a new activity is created), the member variables (whether static or not) for MyLifecycleHandler will be reset to 0.

Does this work for configuration changes?

By default, no. You have to explicitly set configChanges=orientation|screensize (| with anything else you want) in your manifest file and handle the configuration changes, or else your activity will be destroyed and recreated. If you do not set this, your activity's methods will be called in this order: onCreate -> onStart -> onResume -> (now rotate) -> onPause -> onStop -> onDestroy -> onCreate -> onStart -> onResume. As you can see, there is no overlap (normally, two activities overlap very briefly when switching between the two, which is how this backgrounding-detection method works). In order to get around this, you must set configChanges so that your activity is not destroyed. Fortunately, I've had to set configChanges already in all of my projects because it was undesirable for my entire activity to get destroyed on screen rotate/resize, so I've never found this to be problematic. (thanks to dpimka for refreshing my memory on this and correcting me!)

One note:

When I've said "background" here in this answer, I've meant "your app is no longer visible." Android activities can be visible yet not in the foreground (for example, if there's a transparent notification overlay). That's why I've updated this answer to reflect that.

It's important to know that Android has a weird limbo moment when switching activities where nothing is in the foreground. For this reason, if you check if your application is in the foreground when switching between activities (in the same app), you'll be told you're not in the foreground (even though your app is still the active app and is visible).

You can check if your app is in the foreground in your Activity's onPause() method after super.onPause(). Just remember the weird limbo state I just talked about.

You can check if your app is visible (i.e. if it's not in the background) in your Activity's onStop() method after super.onStop().

Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • 1
    This looks interesting - but what happens in low memory situations? It is not guaranteed that onStop() will be called. Could we ever get into the situation where an onStop() is not called and the stopped counter is not incremented - this means that the backgrounded check is no longer reliable? Or would this never happen? – Umbungu Dec 10 '12 at 23:50
  • 1
    Also, will this ignore configuration changes? Or will the application be considered backgrounded if an activity is re-created as a result of a configuration change (e.g. Change in orientation)?. Sorry, for the questions but I think you are onto something and am interested in knowing if it works in these edge cases. – Umbungu Dec 11 '12 at 00:20
  • 1
    @Mewzer: I was going to respond as a comment, but it's going to take a bit of typing to get these answers, so check back in a few minutes and I'll edit my answer. – Cornstalks Dec 11 '12 at 00:21
  • 1
    @Mewzer: You should find your answers now. Let me know if there are any other questions! – Cornstalks Dec 11 '12 at 00:33
  • 2
    @Mewzer: I just added a note that you might be interested in. Specifically, check for backgrounding in `onStop()` after `super.onStop()`. Do not check for backgrounding in `onPause()`. – Cornstalks Dec 11 '12 at 01:02
  • 1
    @Cornstalks you're wrong about configuration changes - they actually do Stop/Resume of activity, unless configChanges=orientation|screensize is set in manifest, which is not by default. But anyway thanks for this hint! – dimsuz Jun 17 '13 at 22:06
  • @dpimka: Woops, you're totally right! I've been setting `configChanges=...` for so many projects that I've been doing it subconsciously now and forgot that this will indeed be problematic. I'll edit the answer to mention that. – Cornstalks Jun 18 '13 at 00:20
  • 1
    @Cornstalks Great, thank you! Already using this method in my app! – dimsuz Jun 18 '13 at 06:48
  • You should put '@Override' annotation before method headers of ActivityLifecycleCallbacks class. In addition to this trifle, good job! – caligari Sep 04 '13 at 15:13
  • 1
    The resumed and stopped count matching well when i make a call to camera intent or image pick from gallery how would i managed to know whether app reached background when user pressed the home button – Software Sainath Nov 29 '13 at 11:06
  • @SoftwareSainath: You can't really distinguish between the user hitting the back button, the home button, or launching another activity. – Cornstalks Nov 29 '13 at 17:16
  • 1
    @Cornstalks: If the app contains some semi-transparent activity, the counting will be wrong, from android document "Pausing and Resuming an Activity", it states that "When a semi-transparent activity obscures your activity, the system calls onPause() and the activity waits in the Paused state", how to deal with this? – Hanon Dec 11 '13 at 05:27
  • @Hanon: Great catch. I've just updated the answer so the logic should now be correct. Hopefully the *One note:* section clarifies some things. Let me know if this update is good. – Cornstalks Dec 14 '13 at 18:11
  • 1
    In `isApplicationInForeground` you've written `resumed > stopped` instead of `resumed > paused`. – kaka Jun 19 '14 at 13:11
  • @Cornstalks what if the user directly press the home button in middle of App. Then the app doesn't return its state that it is in background. Please suggest hoe to handle this scenario – hemanth kumar Mar 04 '15 at 13:15
  • Will app processes be stopped if there is an incoming call also? Thanks so much. – Ruchir Baronia Nov 10 '15 at 04:33
  • i know I'm a bit late but i just wanted to take the time and commend you for this simple and yet beautiful solution! – ruptha Jul 14 '16 at 09:44
  • @Cornstalks I'm new to android development. Would you still recommend this solution to detect if app is in background? Thanks a lot. – Woppi Nov 23 '16 at 11:56
  • In my case: "nothing is in the foreground" between switching activities. – Dmitry Sep 07 '18 at 06:22
  • Although this is a right answer there is no need to implement this yourself, google already added ProcessLifecycleOwner doing the same thing for you using LifecycleObserver. Check https://stackoverflow.com/a/52678290/6600000 – Keivan Esbati Oct 06 '18 at 10:53
  • Not useful now but still I upvoted it because how kind you are! – CopsOnRoad Oct 05 '19 at 09:54
49

Starting support library version 26 you can use ProcessLifecycleOwner, just add it to your dependency like described here, for example:

dependencies {
    def lifecycle_version = "1.1.1"

    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:$lifecycle_version"
    // alternatively - Lifecycles only (no ViewModel or LiveData).
    //     Support library depends on this lightweight import
    implementation "android.arch.lifecycle:runtime:$lifecycle_version"
    annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" // use kapt for Kotlin
}

And then just query ProcessLifecycleOwner whenever you want for app state, examples:

// Check if app is in background
ProcessLifecycleOwner.get().getLifecycle().getCurrentState() == Lifecycle.State.CREATED;

// Check if app is in foreground
ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED);
Ryan M
  • 18,333
  • 31
  • 67
  • 74
Keivan Esbati
  • 3,376
  • 1
  • 22
  • 36
  • 3
    Thanks man, this is the best and easiest way that is suitable in any part of your code specially when using fcm. – Mihae Kheel Jun 19 '19 at 16:22
  • if application is closed completely what would the first method return ? – Evgeniy Mishustin Jul 04 '19 at 13:44
  • @EvgeniyMishustin that depends on the application current state, but you usually would see CREATED then DESTROYED and after that, you wouldn't receive any new events. – Keivan Esbati Jul 04 '19 at 20:08
  • So where is any "IF" statement to see IF app is in the background (foreground)??? – ekashking Nov 11 '19 at 20:51
  • @ekashking just put the entire statement in the if-clause. For example: if(ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) => App is in the foreground – Keivan Esbati Nov 14 '19 at 00:46
  • 1
    [Handling Lifecycles](https://developer.android.com/topic/libraries/architecture/lifecycle) points to a different way of [declaring androidx.lifecycle dependencies](https://developer.android.com/jetpack/androidx/releases/lifecycle#declaring_dependencies). Also, lifecycle-extensions are now listed as deprecated. So In my case the dependencies looked like this: `dependencies { def lifecycle_version = "2.2.0" implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version" }` – Nesho Neshev May 02 '20 at 09:49
  • I think to check if App is in Foreground, we have to use Lifecycle.State.RESUMED – Ramakrishna Joshi Apr 13 '23 at 06:28
  • Depends on what you want to do, if you want to do UI changes or Activity transactions than RESUMED is your signal to go, otherwise STARTED is good. – Keivan Esbati Apr 19 '23 at 02:21
28

Since Android API 16 there is a simple way to check if app is in foreground. It may not be foolproof, but no methods on Android are foolproof. This method is good enough to use when your service receives update from server and has to decide whether to show notification, or not (because if UI is foreground, user will notice the update without notification).

RunningAppProcessInfo myProcess = new RunningAppProcessInfo();
ActivityManager.getMyMemoryState(myProcess);
isInBackground = myProcess.importance != RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
Juozas Kontvainis
  • 9,461
  • 6
  • 55
  • 66
  • should this code be inside Service class or other class e.g Application class? Thanks a lot. – Woppi Nov 23 '16 at 09:37
  • ..wherever you want to use it as the final line is just a boolean you'd check against. – AO_ Jun 22 '17 at 14:38
  • This is the same methodology the AWS Android SDK for push notifications. – spakmad Nov 16 '17 at 14:38
  • Be aware that "The definition of background for purposes of service limitations is distinct from the definition used by memory management; an app might be in the background as pertains to memory management, but in the foreground as pertains to its ability to launch services.)" https://developer.android.com/about/versions/oreo/background.html ( – ARLabs Jul 10 '19 at 10:18
  • Thank you, this worked! I was able to use this code in a [`JobService`](https://developer.android.com/reference/android/app/job/JobService.html) to detect that the service is running in the background. – Michael Osofsky Oct 29 '19 at 18:01
  • However this solution didn't work if I add [`android:process`](https://developer.android.com/guide/topics/manifest/service-element#proc) to the the service definition in the `AndroidManifest.xml` as suggested in https://stackoverflow.com/a/38496939/2848676 – Michael Osofsky Oct 29 '19 at 18:14
  • This was the only one that worked for me when debugging an application, since it would launch the application (including triggering onStart/onResume) even if the screen was off. That creates issues with `startService` since Android O. – Shenk Aug 30 '21 at 15:36
18

Idolon's answer is error prone and much more complicated althought repeatead here check android application is in foreground or not? and here Determining the current foreground application from a background task or service

There is a much more simpler approach:

On a BaseActivity that all Activities extend:

protected static boolean isVisible = false;

 @Override
 public void onResume()
 {
     super.onResume();
     setVisible(true);
 }


 @Override
 public void onPause()
 {
     super.onPause();
     setVisible(false);
 }

Whenever you need to check if any of your application activities is in foreground just check isVisible();

To understand this approach check this answer of side-by-side activity lifecycle: Activity side-by-side lifecycle

Community
  • 1
  • 1
neteinstein
  • 17,529
  • 11
  • 93
  • 123
  • 3
    `Idolon's answer is error prone` - unfortunately I have to agree with you. Based on Dianne Hackborn's comment in the Google Groups I've updated my answer. Check it please for the details. – Volo May 08 '12 at 14:45
  • 2
    This is **not** a foolproof solution either. One scenario is if the user pulled down the notification panel, then neither the `onPause`, `onStop`, nor the `onResume` event is called. So what do you do then if none of these events are fired?! –  Jul 09 '15 at 15:55
  • This led me to this question: http://stackoverflow.com/questions/33657102/method-unnecessarily-getting-called – Ruchir Baronia Nov 11 '15 at 20:24
  • Sadly, but this code works wrong when an activity is started when a screen is off. In this case onResume and onPause are called making isVisible = false. – CoolMind May 10 '16 at 13:49
  • @CoolMind Can you please explain what is the use case where you would launch an activity while in background? – neteinstein May 10 '16 at 17:16
  • @NeTeInStEiN, an application shows once an hour a dialog where a user has to set GPS and mobile internet ON. If the user already set these options, a dialog won't appear. It uses AlarmManager and Service to work. A Service than calls an Activity. – CoolMind May 10 '16 at 17:36
  • Ok, that seems almost right but.. why should you launch the activity while the screen is off? – neteinstein May 12 '16 at 13:35
  • And if the screen is off, wouldn't that make it NOT visible? so, technically this method is returning the correct solution, this method i've used in the past and it will return false if, you are actually on the background, a pop up appears, you drop the status bar, you are launched while the screen is off, and maybe other scenarios that i haven't found. – Jorge Aguilar Jan 30 '17 at 16:18
  • The answer covers the use-case of knowing if any activity screen of an app is visible at a given point in time. But it would not really be able to tell you if an app was put in the background or moved back into the foreground. Because you can not assume that having onResume called means your app was retrieved from the background (like: user pressed home button > after 5 minutes he brings the app back to the foreground). It may just mean that there was a transition from one activity to another. Or am I missing something? – AgentKnopf Mar 09 '17 at 16:51
11

I tried the recommended solution that uses Application.ActivityLifecycleCallbacks and many others, but they didn't work as expected. Thanks to Sarge, I came up with a pretty easy and straightforward solution that I am describing below.

They key of the solution is the fact of understanding that if we have ActivityA and ActivityB, and we call ActivityB from ActivityA (and not call ActivityA.finish), then ActivityB's onStart() will be called before ActivityA onStop().

That's also the main difference between onStop() and onPause() that none did mention in the articles I read.

So based on this Activity's Lifecycle behavior, you can simply count how many times did onStart() and onPause() got called in your program. Note that for each Activity of your program, you must override onStart() and onStop(), in order to increment/decrement the static variable used for counting. Below is the code implementing this logic. Note that I am using a class that extends Application, so dont forget to declare on Manifest.xml inside Application tag: android:name=".Utilities", although it can be implemented using a simple custom class too.

public class Utilities extends Application
{
    private static int stateCounter;

    public void onCreate()
    {
        super.onCreate();
        stateCounter = 0;
    }

    /**
     * @return true if application is on background
     * */
    public static boolean isApplicationOnBackground()
    {
        return stateCounter == 0;
    }

    //to be called on each Activity onStart()
    public static void activityStarted()
    {
        stateCounter++;
    }

    //to be called on each Activity onStop()
    public static void activityStopped()
    {
        stateCounter--;
    }
}

Now on each Activity of our program, we should override onStart() and onStop() and increment/decrement as shown below:

@Override
public void onStart()
{
    super.onStart();
    Utilities.activityStarted();
}

@Override
public void onStop()
{
    Utilities.activityStopped();
    if(Utilities.isApplicationOnBackground())
    {
        //you should want to check here if your application is on background
    }
    super.onStop();
}

With this logic, there are 2 possible cases:

  1. stateCounter = 0 : The number of stopped is equal with the number of started Activities, which means that the application is running on the background.
  2. stateCounter > 0 : The number of started is bigger than the number of stopped, which means that the application is running on the foreground.

Notice: stateCounter < 0 would mean that there are more stopped Activities rather than started, which is impossible. If you encounter this case, then it means that you are not increasing/decreasing the counter as you should.

You are ready to go. You should want to check if your application is on background inside onStop().

Community
  • 1
  • 1
Menelaos Kotsollaris
  • 5,776
  • 9
  • 54
  • 68
  • I'd move `if(Utilities.isApplicationOnBackground()) …` to `Utilities`. Because otherwise only a specific activity will react to the event. – Display Name May 27 '15 at 21:30
10

There is no way, short of you tracking it yourself, to determine if any of your activities are visible or not. Perhaps you should consider asking a new StackOverflow question, explaining what it is you are trying to achieve from a user experience, so we can perhaps give you alternative implementation ideas.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 2
    In android, we have a setting called "Background Data". This setting turns of any background data connection when application is running in background. I want to implement "Background data" toggle for my application, so when none of my activities are visible to the user, I would like my service to stop doing any data transfer, but the moment one of my activities resume, I would like to resume data transfer – cppdev Sep 08 '10 at 13:09
  • 1
    @cppdev: Hopefully, the "data transfer" is being conducted by a `Service`. If so, have your activities notify the service as they appear and disappear. If the `Service` determines that there are no activities visible, and it remains that way for some amount of time, stop the data transfer at the next logical stopping point. Yes, this will require code for each of your activities, but right now, that is unavoidable AFAIK. – CommonsWare Sep 08 '10 at 14:04
  • 1
    If you want to avoid to copy-paste the common code between all your activities, you can create a class `MyActivityClass` inheriting from `Activity` and implementing the lifecycle methods, and make all your activities inherit from `MyActivityClass`. This will no work for `PreferenceActivity` or `MapActivity` though (see [this question](http://stackoverflow.com/questions/6671064/is-it-possible-in-java-to-have-a-class-inherit-from-two-different-classes-dependi)) – Guillaume Brunerie Jul 13 '11 at 14:53
  • @CommonsWare i had tried with OnPause() OnResume() that it is active or not but if my app dosen't view in view screen if it runs in background how check whether it is active or not – Manoj Nov 27 '14 at 13:55
  • @CommonsWare i had tried with OnPause() OnResume() that it is active or not but if my app dosen't view in view screen if it runs in background how check whether it is active or not – Manoj Nov 27 '14 at 13:56
  • @ CommonsWare i had tried with OnPause() OnResume() that it is active or not but if my app dosen't view in view screen if it runs in background how check whether it is active or not – Manoj Nov 27 '14 at 13:56
5

You can use ComponentCallbacks2 to detect if the app is in background. BTW this callback is only available in API Level 14 (Ice Cream Sandwich) and above.

You will get a call to the method:

public abstract void onTrimMemory (int level)

if the level is ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN then the app is in background.

You can implement this interface to an activity, service, etc.

public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 {
   @Override
   public void onConfigurationChanged(final Configuration newConfig) {

   }

   @Override
   public void onLowMemory() {

   }

   @Override
   public void onTrimMemory(final int level) {
     if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
        // app is in background
     }
   }
}
Rohit Arya
  • 6,751
  • 1
  • 26
  • 40
  • 1
    Have tried your answer but is not as reliable. the onTrimMemory callback will not get triggered when the screen is locked nor when pressing the "power" button to lock the screen. It won't also always return TRIM_MEMORY_UI_HIDDEN if your app is visible and you open another app via a status bar notification. The only reliable solution is to implement the ActivityLifecycleCallbacks and adjust it to ones use case. – velval Nov 06 '16 at 11:16
4

Building on @Cornstalks answer to include a couple of useful features.

Extra features:

  • introduced singleton pattern so you can do this anywhere in the application: AppLifecycleHandler.isApplicationVisible() and AppLifecycleHandler.isApplicationInForeground()
  • added handling of duplicate events (see comments // take some action on change of visibility and // take some action on change of in foreground)

App.java

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        registerActivityLifecycleCallbacks(AppLifecycleHandler.getInstance());
    }
}

AppLifecycleHandler.java

public class AppLifecycleHandler implements Application.ActivityLifecycleCallbacks {
    private int resumed;
    private int started;

    private final String DebugName = "AppLifecycleHandler";

    private boolean isVisible = false;
    private boolean isInForeground = false;

    private static AppLifecycleHandler instance;

    public static AppLifecycleHandler getInstance() {
        if (instance == null) {
            instance = new AppLifecycleHandler();
        }

        return instance;
    }

    private AppLifecycleHandler() {
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
    }

    @Override
    public void onActivityResumed(Activity activity) {
        ++resumed;
        android.util.Log.w(DebugName, "onActivityResumed -> application is in foreground: " + (resumed > 0) + " (" + activity.getClass() + ")");
        setForeground((resumed > 0));
    }

    @Override
    public void onActivityPaused(Activity activity) {
        --resumed;
        android.util.Log.w(DebugName, "onActivityPaused -> application is in foreground: " + (resumed > 0) + " (" + activity.getClass() + ")");
        setForeground((resumed > 0));
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }

    @Override
    public void onActivityStarted(Activity activity) {
        ++started;
        android.util.Log.w(DebugName, "onActivityStarted -> application is visible: " + (started > 0) + " (" + activity.getClass() + ")");
        setVisible((started > 0));
    }

    @Override
    public void onActivityStopped(Activity activity) {
        --started;
        android.util.Log.w(DebugName, "onActivityStopped -> application is visible: " + (started > 0) + " (" + activity.getClass() + ")");
        setVisible((started > 0));
    }

    private void setVisible(boolean visible) {
        if (isVisible == visible) {
            // no change
            return;
        }

        // visibility changed
        isVisible = visible;
        android.util.Log.w(DebugName, "App Visiblility Changed -> application is visible: " + isVisible);

        // take some action on change of visibility
    }

    private void setForeground(boolean inForeground) {
        if (isInForeground == inForeground) {
            // no change
            return;
        }

        // in foreground changed
        isInForeground = inForeground;
        android.util.Log.w(DebugName, "App In Foreground Changed -> application is in foreground: " + isInForeground);

        // take some action on change of in foreground

    }

    public static boolean isApplicationVisible() {
        return AppLifecycleHandler.getInstance().started > 0;
    }

    public static boolean isApplicationInForeground() {
        return AppLifecycleHandler.getInstance().resumed > 0;
    }
}
seb
  • 429
  • 4
  • 7
3

The best solution I have come up with uses timers.

You have start a timer in onPause() and cancel the same timer in onResume(), there is 1 instance of the Timer (usually defined in the Application class). The timer itself is set to run a Runnable after 2 seconds (or whatever interval you think is appropriate), when the timer fires you set a flag marking the application as being in the background.

In the onResume() method before you cancel the timer, you can query the background flag to perform any startup operations (e.g. start downloads or enable location services).

This solution allows you to have several activities on the back stack, and doesn't require any permissions to implement.

This solution works well if you use an event bus too, as your timer can simply fire an event and various parts of your app can respond accordingly.

Andrew Kelly
  • 2,180
  • 2
  • 19
  • 27
  • I'm starting to think this is the best (though unfortunate) solution – dhaag23 Oct 27 '15 at 22:53
  • Yep this is the best solution I've managed too. I needed to stop bluetooth scanning when the app wasn't foregrounded, but couldn't just use onpause or stop or destroy because I didn't want to constantly stop and start when the user navigated around the app. – CaptRespect Aug 22 '16 at 18:14
3

If you turn on developer settings "Don't keep actvities" - check only count of created activites is not enough. You must check also isSaveInstanceState. My custom method isApplicationRunning() check is android app is running:

Here my work code:

public class AppLifecycleService implements Application.ActivityLifecycleCallbacks {
    private int created;
    private boolean isSaveInstanceState;
    private static AppLifecycleService instance;

    private final static String TAG = AppLifecycleService.class.getName();

    public static AppLifecycleService getInstance() {
        if (instance == null) {
            instance = new AppLifecycleService();
        }
        return instance;
    }

    public static boolean isApplicationRunning() {
        boolean isApplicationRunning = true;
        if (getCountCreatedActvities() == 0 && !isSaveInstanceState()) {
            isApplicationRunning = false;
        }
        return isApplicationRunning;
    }

    public static boolean isSaveInstanceState() {
        return AppLifecycleService.getInstance().isSaveInstanceState;
    }

    public static int getCountCreatedActvities() {
        return AppLifecycleService.getInstance().created;
    }

    private AppLifecycleService() {
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        this.isSaveInstanceState = true;
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        ++created;
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        --created;
    }

    @Override
    public void onActivityResumed(Activity activity) {   }

    @Override
    public void onActivityPaused(Activity activity) { }


    @Override
    public void onActivityStarted(Activity activity) { }

    @Override
    public void onActivityStopped(Activity activity) { }        

}
Alexei
  • 14,350
  • 37
  • 121
  • 240
2

I did my own implementation of ActivityLifecycleCallbacks. I'm using SherlockActivity, but for normal Activity class might work.

First, I'm creating an interface that have all methods for track the activities lifecycle:

public interface ActivityLifecycleCallbacks{
    public void onActivityStopped(Activity activity);
    public void onActivityStarted(Activity activity);
    public void onActivitySaveInstanceState(Activity activity, Bundle outState);
    public void onActivityResumed(Activity activity);
    public void onActivityPaused(Activity activity);
    public void onActivityDestroyed(Activity activity);
    public void onActivityCreated(Activity activity, Bundle savedInstanceState);
}

Second, I implemented this interface in my Application's class:

public class MyApplication extends Application implements my.package.ActivityLifecycleCallbacks{

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

    @Override
    public void onActivityStopped(Activity activity) {
        Log.i("Tracking Activity Stopped", activity.getLocalClassName());

    }

    @Override
    public void onActivityStarted(Activity activity) {
        Log.i("Tracking Activity Started", activity.getLocalClassName());

    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        Log.i("Tracking Activity SaveInstanceState", activity.getLocalClassName());
    }

    @Override
    public void onActivityResumed(Activity activity) {
        Log.i("Tracking Activity Resumed", activity.getLocalClassName());
    }

    @Override
    public void onActivityPaused(Activity activity) {
        Log.i("Tracking Activity Paused", activity.getLocalClassName());
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        Log.i("Tracking Activity Destroyed", activity.getLocalClassName());
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        Log.i("Tracking Activity Created", activity.getLocalClassName());
    }
}

Third, I'm creating a class that extends from SherlockActivity:

public class MySherlockActivity extends SherlockActivity {

    protected MyApplication nMyApplication;

    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        nMyApplication = (MyApplication) getApplication();
        nMyApplication.onActivityCreated(this, savedInstanceState);
    }

    protected void onResume() {
        // TODO Auto-generated method stub
        nMyApplication.onActivityResumed(this);
        super.onResume();

    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        nMyApplication.onActivityPaused(this);
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        nMyApplication.onActivityDestroyed(this);
        super.onDestroy();
    }

    @Override
    protected void onStart() {
        nMyApplication.onActivityStarted(this);
        super.onStart();
    }

    @Override
    protected void onStop() {
        nMyApplication.onActivityStopped(this);
        super.onStop();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        nMyApplication.onActivitySaveInstanceState(this, outState);
        super.onSaveInstanceState(outState);
    }   
}

Fourth, all class that extend from SherlockActivity, I replaced for MySherlockActivity:

public class MainActivity extends MySherlockActivity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

}

Now, in the logcat you will see the logs programmed in the Interface implementation made in MyApplication.

ClarkXP
  • 1,223
  • 10
  • 23
2

To piggyback on what CommonsWare and Key have said, you could perhaps extend the Application class and have all of your activities call that on their onPause/onResume methods. This would allow you to know which Activity(ies) are visible, but this could probably be handled better.

Can you elaborate on what you have in mind exactly? When you say running in the background do you mean simply having your application still in memory even though it is not currently on screen? Have you looked into using Services as a more persistent way to manage your app when it is not in focus?

Dan
  • 3,182
  • 1
  • 27
  • 27
  • In android, we have a setting called "Background Data". This setting turns of any background data connection when application is running in background. I want to implement "Background data" toggle for my application, so when none of my activities are visible to the user, I would like my service to stop doing any data transfer, but the moment one of my activities resume, I would like to resume data transfer – cppdev Sep 08 '10 at 12:48
  • 1
    `Application` does not have `onPause()` or `onResume()`. – CommonsWare Sep 08 '10 at 14:01
  • 1
    @CommonsWare You are right, I was referring to each individual Activity contacting the Application on their pause/resume. This is basically the idea you just shared on the comment to your answer, though you used Services which I imagine is a smarter move. – Dan Sep 08 '10 at 18:38
2

Offical docs:

The system distinguishes between foreground and background apps. (The definition of background for purposes of service limitations is distinct from the definition used by memory management; an app might be in the background as pertains to memory management, but in the foreground as pertains to its ability to launch services.) An app is considered to be in the foreground if any of the following is true:

  1. It has a visible activity, whether the activity is started or paused.
  2. It has a foreground service.
  3. Another foreground app is connected to the app, either by binding to one of its services or by making use of one of its content providers. For example, the app is in the foreground if another app binds to its:
    • IME
    • Wallpaper service
    • Notification listener
    • Voice or text service

If none of those conditions is true, the app is considered to be in the background.

Uddhav P. Gautam
  • 7,362
  • 3
  • 47
  • 64
2

The only one correct solution:

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        MyApp.mainActivity = this;
        super.onCreate(savedInstanceState);
        ...
    }

MyApp.java:

public class MyApp extends Application implements LifecycleObserver {

    public static MainActivity mainActivity = null;

    @Override
    public void onCreate() {
        super.onCreate();
        ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void onAppBackgrounded() {
        // app in background
        if (mainActivity != null) {
            ...
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void onAppForegrounded() {
        // app in foreground
        if (mainActivity != null) {
            ...
        }
    }

}
Dmitry
  • 14,306
  • 23
  • 105
  • 189
  • I don't see how this solution can possibly give me an answer on a simple question within an IF statement on my activity (or fragment) whether my app is on the background or foreground. Where is the "IF" statement ??? – ekashking Nov 11 '19 at 21:16
2

No any solution work for me, however I propose a raw solution. This should work. If isAppBackground return false, then app must be in foreground.

public static boolean isAppBackground(Context context){
        boolean isBackground=true;
        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        if(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH){
            List<ActivityManager.RunningAppProcessInfo> runningProcesses =activityManager.getRunningAppProcesses();
            for(ActivityManager.RunningAppProcessInfo processInfo:runningProcesses){
                if(processInfo.importance==ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND){
                    for(String activeProcess:processInfo.pkgList){
                        if(activeProcess.equals(context.getPackageName())){
                            isBackground = false;
                        }
                    }
                }
            }
        }else{
            List<ActivityManager.RunningTaskInfo> taskInfo = activityManager.getRunningTasks(1);
            if(taskInfo.size()>0) {
                ComponentName componentName = taskInfo.get(0).topActivity;
                if(componentName.getPackageName().equals(context.getPackageName())){
                    isBackground = false;
                }
            }
        }
        return isBackground;
    }
1

Activity gets paused when a Dialog comes above it so all the recommended solutions are half-solutions. You need to create hooks for dialogs as well.

konmik
  • 3,150
  • 19
  • 15
1

I recommend reading through this page: http://developer.android.com/reference/android/app/Activity.html

In short, your activity is no longer visible after onStop() has been called.

Ferran Maylinch
  • 10,919
  • 16
  • 85
  • 100
Key
  • 6,986
  • 1
  • 23
  • 15
  • 3
    I have around 10 activities in my application. So I want to know if none of them if visible to the user. In all, I want to know if my application as a whole is running in background – cppdev Sep 08 '10 at 11:20
  • So then you keep track of all 10-ish. Or, as CommonsWare suggested, explain what you are trying to do. – Key Sep 08 '10 at 12:31
  • 3
    This isn't correct. Your Activity is visible until `onStop`; between `onPause` and `onStop` it's *visible*, but not *in the foreground*. – nickgrim Nov 20 '15 at 11:35
  • @nickgrim: what is not correct? I stated that an activity is no longer visible after `onStop()` is called, which is aligned with what you wrote. – Key May 20 '16 at 08:44
  • @Key: You originally said until `onPause` is called: a recent edit has corrected you. – nickgrim May 20 '16 at 11:27
1

Since it isn't already mentioned, I will suggest the readers to explore ProcessLifecycleOwner available through Android Architecture components

Rachit Mishra
  • 6,101
  • 4
  • 30
  • 51
1

This code will check foreground and background in any condition:

Java Code:

private static boolean isApplicationForeground(Context context) {
    KeyguardManager keyguardManager =
            (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);

    if (keyguardManager.isKeyguardLocked()) {
        return false;
    }
    int myPid = Process.myPid();

    ActivityManager activityManager =
            (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

    List<ActivityManager.RunningAppProcessInfo> list;

    if ((list = activityManager.getRunningAppProcesses()) != null) {
        for (ActivityManager.RunningAppProcessInfo aList : list) {
            ActivityManager.RunningAppProcessInfo info;
            if ((info = aList).pid == myPid) {
                return info.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
            }
        }
    }
    return false;
}

Kotlin Code:

private fun isApplicationForeground(context: Context): Boolean {
        val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
        if (keyguardManager.isKeyguardLocked) {
            return false
        }
        val myPid = Process.myPid()
        val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        var list: List<ActivityManager.RunningAppProcessInfo>
        if (activityManager.runningAppProcesses.also { list = it } != null) {
            for (aList in list) {
                var info: ActivityManager.RunningAppProcessInfo
                if (aList.also { info = it }.pid == myPid) {
                    return info.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
                }
            }
        }
        return false
    }
Yeahia2508
  • 7,526
  • 14
  • 42
  • 71
1

Simple and straight-forward answer:

override fun onPause() {
    Log.i("APP LIFECYCLE", "App Enter BACKground")
    isForeground = false
    super.onPause()
}

override fun onResume() {
    Log.i("APP LIFECYCLE", "App Enter FOREground")
    isForeground = true
    super.onResume()
}

Then just use the isForeground property of your activity to check the status.

SHANNAX
  • 322
  • 3
  • 5
0

Another solution for this old post (for those that it might help) :


<application android:name=".BaseApplication" ... >

public class BaseApplication extends Application {

    private class Status {
        public boolean isVisible = true;
        public boolean isFocused = true;
    }

    private Map<Activity, Status> activities;

    @Override
    public void onCreate() {
        activities = new HashMap<Activity, Status>();
        super.onCreate();
    }

    private boolean hasVisibleActivity() {
        for (Status status : activities.values())
            if (status.isVisible)
                return true;
        return false;
    }

    private boolean hasFocusedActivity() {
        for (Status status : activities.values())
            if (status.isFocused)
                return true;
        return false;
    }

    public void onActivityCreate(Activity activity, boolean isStarting) {
        if (isStarting && activities.isEmpty())
            onApplicationStart();
        activities.put(activity, new Status());
    }

    public void onActivityStart(Activity activity) {
        if (!hasVisibleActivity() && !hasFocusedActivity())
            onApplicationForeground();
        activities.get(activity).isVisible = true;
    }

    public void onActivityWindowFocusChanged(Activity activity, boolean hasFocus) {
        activities.get(activity).isFocused = hasFocus;
    }

    public void onActivityStop(Activity activity, boolean isFinishing) {
        activities.get(activity).isVisible = false;
        if (!isFinishing && !hasVisibleActivity() && !hasFocusedActivity())
            onApplicationBackground();
    }

    public void onActivityDestroy(Activity activity, boolean isFinishing) {
        activities.remove(activity);
        if(isFinishing && activities.isEmpty())
            onApplicationStop();
    }

    private void onApplicationStart() {Log.i(null, "Start");}
    private void onApplicationBackground() {Log.i(null, "Background");}
    private void onApplicationForeground() {Log.i(null, "Foreground");}
    private void onApplicationStop() {Log.i(null, "Stop");}

}

public class MyActivity extends BaseActivity {...}

public class BaseActivity extends Activity {

    private BaseApplication application;

    @Override
    protected void onCreate(Bundle state) {
        application = (BaseApplication) getApplication();
        application.onActivityCreate(this, state == null);
        super.onCreate(state);
    }

    @Override
    protected void onStart() {
        application.onActivityStart(this);
        super.onStart();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        application.onActivityWindowFocusChanged(this, hasFocus);
        super.onWindowFocusChanged(hasFocus);
    }

    @Override
    protected void onStop() {
        application.onActivityStop(this, isFinishing());
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        application.onActivityDestroy(this, isFinishing());
        super.onDestroy();
    }

}
alex
  • 5,661
  • 6
  • 33
  • 54
0

See the comment in the onActivityDestroyed function.

Works with SDK target version 14> :

import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;

public class AppLifecycleHandler implements Application.ActivityLifecycleCallbacks {

    public static int active = 0;

    @Override
    public void onActivityStopped(Activity activity) {
        Log.i("Tracking Activity Stopped", activity.getLocalClassName());
        active--;
    }

    @Override
    public void onActivityStarted(Activity activity) {
        Log.i("Tracking Activity Started", activity.getLocalClassName());
        active++;
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        Log.i("Tracking Activity SaveInstanceState", activity.getLocalClassName());
    }

    @Override
    public void onActivityResumed(Activity activity) {
        Log.i("Tracking Activity Resumed", activity.getLocalClassName());
        active++;
    }

    @Override
    public void onActivityPaused(Activity activity) {
        Log.i("Tracking Activity Paused", activity.getLocalClassName());
        active--;
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        Log.i("Tracking Activity Destroyed", activity.getLocalClassName());
        active--;

        // if active var here ever becomes zero, the app is closed or in background
        if(active == 0){
            ...
        }

    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        Log.i("Tracking Activity Created", activity.getLocalClassName());
        active++;
    }
}
ramden
  • 798
  • 1
  • 9
  • 25
0

You should use a shared preference to store the property and act upon it using service binding from your activities. If you use binding only, (that is never use startService), then your service would run only when you bind to it, (bind onResume and unbind onPause) that would make it run on foreground only, and if you do want to work on background you can use the regular start stop service.

Ofek Ron
  • 8,354
  • 13
  • 55
  • 103
0

I think this question should be more clear. When? Where? What is your specific situation you want to konw if your app is in background?

I just introduce my solution in my way.
I get this done by using the field "importance" of RunningAppProcessInfo class in every activity's onStop method in my app, which can be simply achieved by providing a BaseActivity for other activities to extend which implements the onStop method to check the value of "importance". Here is the code:

public static boolean isAppRunning(Context context) {
    ActivityManager activityManager = (ActivityManager) context
        .getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningAppProcessInfo> appProcesses = activityManager
        .getRunningAppProcesses();
    for (RunningAppProcessInfo appProcess : appProcesses) {
        if (appProcess.processName.equals(context.getPackageName())) {
            if (appProcess.importance != RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE) {
                return true;
            } 
        }
    }
    return false;
}
PatJ
  • 5,996
  • 1
  • 31
  • 37
wxf04125
  • 9
  • 1
0

What about using getApplicationState().isInForeground() ?

Jono
  • 17,341
  • 48
  • 135
  • 217
0

In my opinion, many answers introduce a heavy load of code and bring lots of complexity and non-readability.

When people ask on SO how to communicate between a Service and a Activity, I usually advice to use the LocalBroadcastManager.


Why?

Well, by quoting the docs:

  • You know that the data you are broadcasting won't leave your app, so don't need to worry about leaking private data.

  • It is not possible for other applications to send these broadcasts to your app, so you don't need to worry about having security holes they can exploit.

  • It is more efficient than sending a global broadcast through the system.

Not in the the docs:

  • It does not require external libraries
  • The code is minimal
  • It's fast to implement and understand
  • No custom self-implemented callbacks / ultra-singleton / intra-process pattern whatsoever...
  • No strong references on Activity, Application, ...

Description

So, you want to check if any of the Activity is currently in the foreground. You usually do that in a Service, or your Application class.

This means, your Activity objects become the sender of a signal (I'm on / I'm off). Your Service, on the other hand, becomes the Receiver.

There are two moments in which your Activity tells you if it's going in the foreground or in the background (yes only two... not 6).

When the Activity goes into the foreground, the onResume() method is triggered (also called after onCreate()).

When the Activity goes in the back, onPause() is called.

These are the moments in which your Activity should send the signal to your Service to describe its state.

In case of multiple Activity's, remember the an Activity goes into the background first, then another one comes into the foreground.

So the situation would be:*

Activity1 -- send --> Signal:OFF
Activity2 -- send --> Signal:ON

The Service / Application will simply keep listening for those signals and act accordingly.


Code (TLDR)

Your Service must implement a BroadcastReceiver in order to listen for signals.

this.localBroadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // received data if Activity is on / off
    }
}

public static final IntentFilter SIGNAL_FILTER = new IntentFilter("com.you.yourapp.MY_SIGNAL") 

Register the Receiver in Service::onCreate()

@Override
protected void onCreate() {
    LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, SIGNAL_FILTER);
}

Un-register it in Service::onDestroy()

@Override
protected void onDestroy() {
    // I'm dead, no need to listen to anything anymore.
    LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
}

Now your Activity's must communicated their state.

In Activity::onResume()

Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put ON boolean in intent    
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);

In Activity::onPause()

Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put OFF boolean in intent    
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);

A very, very common situation

Developer: I want to send data from my Service and update the Activity. How do I check if the Activity is in the foreground?

There is usually no need to check if the Activity is in the foreground or not. Just send the data via LocalBroadcastManager from your Service. If the Activity is on, then it will respond and act.

For this very common situation, the Service becomes the sender, and the Activity implements the BroadcastReceiver.

So, create a Receiver in your Activity. Register it in onResume() and un-register it in onPause(). There is no need to use the other life-cycle methods.

Define the Receiver behavior in onReceive() (update ListView, do this, do that, ...).

This way the Activity will listen only if it's in the foreground and nothing will happen if it's in the back or is destroyed.

In case of multiple Activity's, whichever Activity is on will respond (if they also implement the Receiver).

If all are in the background, nobody will respond and the signal will simply get lost.

Send the data from the Service via Intent (see code above) by specifying the signal ID.


payloc91
  • 3,724
  • 1
  • 17
  • 45
0
fun isAppInForeground(): Boolean {
    val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager ?: return false

    val appProcesses = activityManager.runningAppProcesses ?: return false

    val packageName = packageName
    for (appProcess in appProcesses) {
        if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName == packageName) {
            return true
        }
    }

    return false
}
ayoub laaziz
  • 1,196
  • 9
  • 12
0

None of the answers quite fitted the specific case if you're looked to know if a specfic activity is in the forground and if you're an SDK without direct access to the Application. For me I was in background thread having just recieved a push notification for a new chat message and only want to display a system notification if the chat screen isn't in the foreground.

Using the ActivityLifecycleCallbacks that as been recommended in other answers I've created a small util class that houses the logic to whether MyActivity is in the Foreground or not.

class MyActivityMonitor(context: Context) : Application.ActivityLifecycleCallbacks {

private var isMyActivityInForeground = false

init {
    (context.applicationContext as Application).registerActivityLifecycleCallbacks(this)
}

fun isMyActivityForeground() = isMyActivityInForeground

override fun onActivityPaused(activity: Activity?) {
    if (activity is MyActivity) {
        isMyActivityInForeground = false
    }
}

override fun onActivityResumed(activity: Activity?) {
    if (activity is MyActivity) {
        isMyActivityInForeground = true
    }
}

}

scottyab
  • 23,621
  • 16
  • 94
  • 105
0

Another way with no additional dependency is this one:

Simply add this method to your Application Class and call it in onCreate()

var isInBackground = true

private fun setupActivityLifecycleCallbacks() {
    registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
        override fun onActivityStarted(activity: Activity) {}
        override fun onActivityResumed(activity: Activity) {
            isInBackground = false
        }
        override fun onActivityPaused(activity: Activity) {
            isInBackground = true
        }
        override fun onActivityStopped(activity: Activity) {}
        override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
        override fun onActivityDestroyed(activity: Activity) {}
    })
}

AFAIK you can even make isInBackground static so you can access it without context using a companion object

Merthan Erdem
  • 5,598
  • 2
  • 22
  • 29
0

How about something like this:

boolean isBackgrounded() {
    try {
        context.startService(new Intent(action));
        return false;
    }
    catch (IllegalStateException exc) {
        // "Not allowed to start service Intent: app is in background"
        return true;
    }
}
Waxrat
  • 510
  • 2
  • 11
0

This is working as of 2023

1-Please go to your application class. ( if you havent any application class then please add a class that extends Application)

2-Then add private static variable in your application class to store the state.

3-Then implement LifecycleEventObserver in your application and its single method "onStateChanged"

4-Lastly, add static method to get the state of private variable from any activity or fragment in your application

public class MyApp extends Application implements LifecycleEventObserver{

    private static boolean activityVisible;

    @Override
    public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event)
    {
        if (event == Lifecycle.Event.ON_STOP) {
            activityVisible = false;
        }
        else if (event == Lifecycle.Event.ON_PAUSE){
            activityVisible = false;
        }
        else if (event == Lifecycle.Event.ON_RESUME){
            activityVisible = true;
        }
        else if (event == Lifecycle.Event.ON_START) {
            activityVisible = true;
        }
    }

    public static boolean checkIfActivityVisible(){
        return activityVisible;
    }

}
smoothumut
  • 3,423
  • 1
  • 25
  • 35
0

Here are multiple ways

  1. Using LifecycleEventObserver. Here ProcessLifecycleOwner provides lifecycle for the whole application process. So onStateChanged is called when app goes to foreground/background and not called between Activity Switches.
import android.app.Application
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner

class TestApplication: Application(), LifecycleEventObserver {

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

    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        Log.i("AppForegrounded", "Hello event ${event}")
        if (event == Lifecycle.Event.ON_RESUME) {
            isAppInForeground = true
        } else {
            isAppInForeground = false
        }
    }

    companion object {
        var isAppInForeground = false
    }
}

and then in Activity use it as

TestApplication.isAppInForeground

Make sure you mention this Application class in Manifest file

<manifest>
    <application
           android:name=".app.TestApplication"
    </application>
</manifest>

We can also make the field isAppInForeground observable so that we can listen to changes instead of checking if app is in foreground before making some operation.

  1. Using DefaultLifecycleObserver. Here ProcessLifecycleOwner provides lifecycle for the whole application process. So onResume or onPause is called when app goes to foreground/background and not called between Activity Switches.
class TestApplication: Application(), DefaultLifecycleObserver {

    override fun onCreate() {
        super<Application>.onCreate()
        ProcessLifecycleOwner.get().lifecycle.addObserver(this);
    }

    override fun onResume(owner: LifecycleOwner) {
        super.onResume(owner)
        isAppInForeground = true
    }

    override fun onPause(owner: LifecycleOwner) {
        super.onPause(owner)
        isAppInForeground = false
    }

    companion object {
        var isAppInForeground = false
    }
}
  1. Using ProcessLifecycleOwner's currentState field
val isAppInForeground = ProcessLifecycleOwner.get().lifecycle.currentState == Lifecycle.State.RESUMED
val isAppInBackground = ProcessLifecycleOwner.get().lifecycle.currentState == Lifecycle.State.CREATED

Ramakrishna Joshi
  • 1,442
  • 17
  • 22
-1

It might be too late to answer but if somebody comes visiting then here is the solution I suggest, The reason(s) an app wants to know it's state of being in background or coming to foreground can be many, a few are, 1. To show toasts and notifications when the user is in BG. 2.To perform some tasks for the first time user comes from BG, like a poll, redraw etc.

The solution by Idolon and others takes care of the first part, but does not for the second. If there are multiple activities in your app, and the user is switching between them, then by the time you are in second activity, the visible flag will be false. So it cannot be used deterministically.

I did something what was suggested by CommonsWare, "If the Service determines that there are no activities visible, and it remains that way for some amount of time, stop the data transfer at the next logical stopping point."

The line in bold is important and this can be used to achieve second item. So what I do is once I get the onActivityPaused() , don not change the visible to false directly, instead have a timer of 3 seconds (that is the max that the next activity should be launched), and if there is not onActivityResumed() call in the next 3 seconds, change visible to false. Similarly in onActivityResumed() if there is a timer then I cancel it. To sum up,the visible becomes isAppInBackground.

Sorry cannot copy-paste the code...

Sriram
  • 55
  • 6
-2

In my activities onResume and onPause I write an isVisible boolean to SharedPrefences.

    SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    Editor editor = sharedPrefs.edit();
    editor.putBoolean("visible", false);
    editor.commit();

And read it elsewhere when needed via,

    // Show a Toast Notification if App is not visible (ie in background. Not running, etc) 
    SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
    if(!sharedPrefs.getBoolean("visible", true)){...}

Maybe not elegant, but it works for me...

mtwagner
  • 466
  • 6
  • 12
-3

I would like to recommend you to use another way to do this.

I guess you want to show start up screen while the program is starting, if it is already running in backend, don't show it.

Your application can continuously write current time to a specific file. While your application is starting, check the last timestamp, if current_time-last_time>the time range your specified for writing the latest time, it means your application is stopped, either killed by system or user himself.