Checking if an Android application is running in the background
Asked Answered
P

38

380

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

Pandit answered 8/9, 2010 at 11:4 Comment(10)
possible duplicate of How to determine if one of my activities is in the foregroundCurnin
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() { }Porta
@ChuckD - that would make sense, which is what the Android SDK seems to like to avoid doing at times. :/Insured
codingaffairs.blogspot.com/2016/05/…Cheslie
iOS has this in spades, not sure why Google makes this so hard. It's such an obvious need.Fuchsin
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 workDehypnotize
Go at @user1269737 answer. That should be the correct answer!Dupin
Most recent/correct solution still far down: https://mcmap.net/q/81524/-checking-if-an-android-application-is-running-in-the-backgroundEisteddfod
Although it works there is no need to implement this yourself, google already added ProcessLifecycleOwner doing the same thing for you using LifecycleObserver. Check https://mcmap.net/q/81524/-checking-if-an-android-application-is-running-in-the-backgroundSophy
ProcessLifecycleOwner is the newest solutionMazurek
G
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.

Geminian answered 2/5, 2011 at 20:20 Comment(25)
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.Skyla
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.Bedpan
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.Portable
@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). :(Sector
Android is such a freaking wreck. No one thought that someone might want to persist app level data? Give me a breakFloribunda
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.Austere
+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.Cathee
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. :/Orchard
@idolon Why when I access static field from BroadcastReceiver is always false? How can i know if is visible from BrowadcastReceiver?Critique
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.Vidicon
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...Livable
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?!Simar
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.Alrich
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.Cardie
@Idolon Please consider including an option described in my answer https://mcmap.net/q/81524/-checking-if-an-android-application-is-running-in-the-background 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.Cachucha
Can i check third party application Like any third party app is working in backgroud or notStraightjacket
I think you must mark MyApplication.activityVisible volatileLarena
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.Adhern
I made this utility class that solves this issue without any special permissions or API level restrictions gist.github.com/pantos27/6faad313ba364c947e2487e80aa25c86Phares
That's why I choose iPhone... I'm kidding because they have the same issue on iOS.Typebar
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://mcmap.net/q/81524/-checking-if-an-android-application-is-running-in-the-backgroundSophy
The right solution is only a solution if you have only one activity, otherwise you will have a mess.Characteristically
Your "right" solution is wrong according to androids definition... According to 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 itPurree
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 itPurree
@Bedpan 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://mcmap.net/q/81524/-checking-if-an-android-application-is-running-in-the-backgroundLourielouse
A
328

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

Aldos answered 13/2, 2018 at 13:10 Comment(20)
This should definitely be the correct answer! It worked like a charm :DDupin
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()Implication
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.Perithecium
Although this is a right answer there is no need to implement callbacks, you can just query ProcessLifecycleOwner whenever you want. Check https://mcmap.net/q/81524/-checking-if-an-android-application-is-running-in-the-backgroundSophy
Great Solution, Better than every answers given here... Works Perfectly...Bushhammer
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?Mcdaniels
what will be the result of closing application completely ? This means nothing in foreground and nothing in backgroundPrecondition
Sorry, but where is the androix version of ProcessLifecycleOwner? Here is documented: developer.android.com/reference/androidx/lifecycle/… but I cannot find it importing neither androidx.lifecycle:lifecycle-runtime nor androidx.lifecycle:lifecycle-extensionsRossini
@ARLabs, implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'.Cardie
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!Diehl
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 ???Uis
Can I use this code to check if another application is running in the background from my application?Bullring
don't forget adding the class which extends Application to the manifest under the application tag like this: android:name=".ArchLifecycleApp"Madaras
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. ThanksCommunitarian
@acntwww did you find a solution for multi-process applications? I need it to work for activities in a separate process.Deprivation
It worked fine, BUT DO NOT FORGET ADD THIS LINE TO: manifests (inside application tag): '<application android:name=".LifecycleApp">'Morose
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://mcmap.net/q/81524/-checking-if-an-android-application-is-running-in-the-background -> this one fixes the problem.Cyril
The @OnLifecycleEvent annotation is deprecated. It is recommended to use DefaultLifecycleObserver or LifecycleEventObserver instead. Source: developer.android.com/reference/androidx/lifecycle/…Aalborg
Also, jCenter is deprecated.Aalborg
Deprecated. Use Application.ActivityLifecycleCallbacksGawky
P
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().

Perithecium answered 10/12, 2012 at 21:59 Comment(21)
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?Tighten
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.Tighten
@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.Perithecium
@Mewzer: You should find your answers now. Let me know if there are any other questions!Perithecium
@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().Perithecium
@Perithecium 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!Microsporophyll
@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.Perithecium
@Perithecium Great, thank you! Already using this method in my app!Microsporophyll
You should put '@Override' annotation before method headers of ActivityLifecycleCallbacks class. In addition to this trifle, good job!Duplet
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 buttonSubstantialize
@SoftwareSainath: You can't really distinguish between the user hitting the back button, the home button, or launching another activity.Perithecium
@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?Sussex
@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.Perithecium
In isApplicationInForeground you've written resumed > stopped instead of resumed > paused.Tish
@Perithecium 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 scenarioDictum
Will app processes be stopped if there is an incoming call also? Thanks so much.Rogers
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!Hohenlohe
@Perithecium I'm new to android development. Would you still recommend this solution to detect if app is in background? Thanks a lot.Crural
In my case: "nothing is in the foreground" between switching activities.Typebar
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://mcmap.net/q/81524/-checking-if-an-android-application-is-running-in-the-backgroundSophy
Not useful now but still I upvoted it because how kind you are!Meghannmegiddo
S
51

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);
Sophy answered 6/10, 2018 at 10:50 Comment(8)
Thanks man, this is the best and easiest way that is suitable in any part of your code specially when using fcm.Caroncarotene
if application is closed completely what would the first method return ?Precondition
@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.Sophy
So where is any "IF" statement to see IF app is in the background (foreground)???Uis
@Uis just put the entire statement in the if-clause. For example: if(ProcessLifecycleOwner.get().getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) => App is in the foregroundSophy
Handling Lifecycles points to a different way of declaring androidx.lifecycle 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" }Kathikathiawar
I think to check if App is in Foreground, we have to use Lifecycle.State.RESUMEDLourielouse
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.Sophy
C
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;
Cachucha answered 20/9, 2016 at 8:27 Comment(7)
should this code be inside Service class or other class e.g Application class? Thanks a lot.Crural
..wherever you want to use it as the final line is just a boolean you'd check against.Souterrain
This is the same methodology the AWS Android SDK for push notifications.Agni
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.)" developer.android.com/about/versions/oreo/background.html (Rossini
Thank you, this worked! I was able to use this code in a JobService to detect that the service is running in the background.Volatile
However this solution didn't work if I add android:process to the the service definition in the AndroidManifest.xml as suggested in https://mcmap.net/q/82470/-android-service-stops-when-app-is-closedVolatile
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.Moiety
T
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

Tungstate answered 10/4, 2012 at 18:54 Comment(9)
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.Geminian
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?!Simar
This led me to this question: #33657602Rogers
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.Cardie
@Cardie Can you please explain what is the use case where you would launch an activity while in background?Tungstate
@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.Cardie
Ok, that seems almost right but.. why should you launch the activity while the screen is off?Tungstate
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.Pedicle
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?Brasilein
N
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().

Nadda answered 27/5, 2015 at 16:45 Comment(1)
I'd move if(Utilities.isApplicationOnBackground()) … to Utilities. Because otherwise only a specific activity will react to the event.Amice
T
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.

Trueman answered 8/9, 2010 at 11:35 Comment(6)
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 transferPandit
@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.Trueman
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)Laflamme
@Trueman 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 notSolanum
@Trueman 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 notSolanum
@ 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 notSolanum
S
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
     }
   }
}
Selenite answered 30/3, 2016 at 21:9 Comment(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.Wavelet
B
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;
    }
}
Befriend answered 23/11, 2016 at 14:55 Comment(0)
C
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.

Capuchin answered 13/2, 2014 at 3:16 Comment(2)
I'm starting to think this is the best (though unfortunate) solutionGodson
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.Crape
M
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) { }        

}
Moreland answered 29/1, 2017 at 16:57 Comment(0)
H
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?

Haruspicy answered 8/9, 2010 at 12:38 Comment(3)
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 transferPandit
Application does not have onPause() or onResume().Trueman
@Trueman 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.Haruspicy
T
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.

Tole answered 23/1, 2013 at 0:14 Comment(0)
R
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.

Renwick answered 1/2, 2018 at 0:52 Comment(0)
T
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) {
            ...
        }
    }

}
Typebar answered 7/9, 2018 at 7:40 Comment(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 ???Uis
W
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;
    }
Wallpaper answered 1/8, 2021 at 21:21 Comment(0)
D
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.

Distaste answered 8/9, 2010 at 11:12 Comment(5)
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 backgroundPandit
So then you keep track of all 10-ish. Or, as CommonsWare suggested, explain what you are trying to do.Distaste
This isn't correct. Your Activity is visible until onStop; between onPause and onStop it's visible, but not in the foreground.Constantia
@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.Distaste
@Key: You originally said until onPause is called: a recent edit has corrected you.Constantia
B
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.

Backdrop answered 3/10, 2015 at 9:39 Comment(0)
B
1

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

Broadleaved answered 29/1, 2018 at 11:46 Comment(0)
E
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
    }
Exemplification answered 7/11, 2020 at 8:21 Comment(0)
I
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.

Ingraham answered 15/7, 2022 at 10:12 Comment(0)
O
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();
    }

}
Overlong answered 1/3, 2014 at 21:48 Comment(0)
B
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++;
    }
}
Baeza answered 8/12, 2014 at 13:5 Comment(0)
G
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.

Gel answered 18/12, 2014 at 12:24 Comment(0)
C
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;
}
Congressman answered 20/3, 2015 at 3:21 Comment(1)
This is not a recommended solution as stated in @Idolon's answer.Cardie
I
0

What about using getApplicationState().isInForeground() ?

Inexhaustible answered 15/2, 2016 at 14:30 Comment(0)
B
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.


Busiek answered 30/1, 2018 at 13:56 Comment(0)
T
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
}
Tung answered 15/4, 2019 at 13:21 Comment(0)
M
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
    }
}

}

Malaysia answered 25/9, 2019 at 17:5 Comment(0)
P
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

Pecksniffian answered 6/7, 2021 at 20:53 Comment(0)
S
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;
    }
}
Sigh answered 2/9, 2021 at 17:4 Comment(1)
Using exceptions to control application flow is, generally, a bad idea.Aalborg
O
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;
    }

}
Ortrud answered 10/3, 2023 at 9:11 Comment(0)
L
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

Lourielouse answered 13/4, 2023 at 7:28 Comment(0)
F
0

val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                val runningProcesses = activityManager.runningAppProcesses
                if (runningProcesses != null) {
                    for (processInfo in runningProcesses) {
                        if (processInfo.pkgList != null) {
                            for (pkg in processInfo.pkgList) {
                                if (pkg == packageName) {
                                    return true
                                }
                            }
                        }
                    }
                }
            } else {
                // For versions before Lollipop
                val taskInfo = activityManager.getRunningTasks(1)
                if (taskInfo != null && taskInfo.size > 0) {
                    val topActivity = taskInfo[0].topActivity
                    if (topActivity != null && topActivity.packageName == packageName) {
                        return true
                    }
                }
            }
Feral answered 9/1 at 8:22 Comment(0)
C
-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...

Crevasse answered 3/10, 2013 at 8:0 Comment(0)
B
-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...

Berton answered 18/6, 2012 at 14:53 Comment(0)
M
-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.

Mump answered 26/4, 2013 at 8:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.