By background, I mean none of the application's activities are currently visible to the user?
In order to make Android allow apps to run in background, all you need to do is press the open padlock icon right next to them. Once the open padlock changes and you get the “Locked” pop-up notification on your screen, you're all set!
There are few ways to detect whether your application is running in the background, but only one of them is completely reliable:
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.
The wrong one
I used to suggest the following solution:
You can detect currently foreground/background application with
ActivityManager.getRunningAppProcesses()
which returns a list ofRunningAppProcessInfo
records. To determine if your application is on the foreground checkRunningAppProcessInfo.importance
field for equality toRunningAppProcessInfo.IMPORTANCE_FOREGROUND
whileRunningAppProcessInfo.processName
is equal to your application package name.Also if you call
ActivityManager.getRunningAppProcesses()
from your application UI thread it will return importanceIMPORTANCE_FOREGROUND
for your task no matter whether it is actually in the foreground or not. Call it in the background thread (for example viaAsyncTask
) 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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With