4

It seems like tones of answers on this question but all incomplete. A have an app with multiple activities. All I need is an IF statement meaning that IF my app entered a background I do this ... and if it entered foreground I do this ...

!!! Keep in mind that if I'm switching from one activity to another meaning that my first activity stops, that doesn't mean that my app entered background - it's just one activity's replaced with another one.

ekashking
  • 387
  • 6
  • 19

4 Answers4

3

First add some of the following necessary dependencies in app level gradle

dependencies {
def lifecycle_version = "2.1.0"

// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
// alternatively - just ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" // For Kotlin use lifecycle-viewmodel-ktx
// alternatively - just LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
// alternatively - Lifecycles only (no ViewModel or LiveData). Some UI
//     AndroidX libraries use this lightweight import for Lifecycle
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"

annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" // For Kotlin use kapt instead of annotationProcessor
// alternately - if using Java8, use the following instead of lifecycle-compiler
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"

// optional - ReactiveStreams support for LiveData
implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version" // For Kotlin use lifecycle-reactivestreams-ktx

// optional - Test helpers for LiveData
testImplementation "androidx.arch.core:core-testing:$lifecycle_version"

}

You may refer to the latest version of dependency here

https://developer.android.com/jetpack/androidx/releases/lifecycle?authuser=1

Your app must extend the Application class and override the following the methods given in example below.

You can simply achieve the same functionality using lifecycle-aware component of arch libraries. I have just posted one sample code for Kotlin and Java for your use case.

The Java version.

public class YourApp extends Application implements LifecycleObserver {

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

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

// Application level lifecycle events
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onEnteredForeground() {
    //Timber.d("Application did enter foreground");

}

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onEnteredBackground() {
   // Timber.d("Application did enter background");
}

}

Kotlin version:

class ZumeApp : Application(), LifecycleObserver {

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

// Application level lifecycle events
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onEnteredForeground() {
    Timber.d("Application did enter foreground")

}

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onEnteredBackground() {
    Timber.d("Application did enter background")
}
}

I hope it will help you. Leave a comment if it does not work or refer to the following article in android docs.

https://developer.android.com/topic/libraries/architecture/lifecycle?authuser=1

Farruh Habibullaev
  • 2,342
  • 1
  • 26
  • 33
  • Yes... I now that ... but how do I use the observer later on in my activity ... checking if it's in background or foreground??? – ekashking Nov 11 '19 at 22:05
  • Then, a simple way is to create a volatile state variable in your app class, your app class is singleton for your whole app by default, update that volatile state variable when application lifecycle is updated. From your any activity / fragment / dialog which is component in your app container, you can access that state variable like this, for example YourApp.state which returns boolean or string or integer, depending on how you define it. Since your app is container for all the components in your app, that variable is always available from your component. It is one of ugly way of doing it. – Farruh Habibullaev Nov 11 '19 at 22:24
  • 2
    `@OnLifecycleEvent` is deprecated. https://developer.android.com/jetpack/androidx/releases/lifecycle#2.4.0-beta01 – Akito Nov 19 '21 at 15:14
1

The ProcessLifecycleOwner is something that is helpful. It mentions It is useful for use cases where you would like to react on your app coming to the foreground or going to the background and you don't need a milliseconds accuracy in receiving lifecycle events.
- https://developer.android.com/reference/androidx/lifecycle/ProcessLifecycleOwner.html

Look at the events Lifecycle.Event.ON_PAUSE and Lifecycle.Event.ON_RESUME

Vino
  • 1,544
  • 1
  • 18
  • 26
  • Hey, I posted my own answer. Can you please check it out whether it's a proper way or not? I'm more concerned if `ProcessLifecycleOwner` is supported by API starting from SDK 22 and up. Thanks! – ekashking Nov 11 '19 at 23:59
1

Ok, it's accomplished by using ProcessLifecycleOwner with an observer. I got this on my fragment. The only time when the state changes from ON_PAUSE to ON_RESUME and back is if when the entire app goes into the background and comes back. And then, depending on the state (in my example) I'm either getting my location using background method or on the foreground callback.

@Override
public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {

    setRetainInstance(true);
    //...
    // some other stuff
    //...

    ProcessLifecycleOwner.get().getLifecycle().addObserver(new LifecycleEventObserver() {
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {

            if (event == Lifecycle.Event.ON_PAUSE) {
                Log.e("Lifecycle", "Background");


                getLocationFromBackground();


            } else if (event == Lifecycle.Event.ON_RESUME) {
                Log.e("Lifecycle", "Foreground");

                getLocationFromForeground();
            }
        }
    });

return view;
}

private void getLocationFromBackground() {
    // some code
}


private void getLocationFromForeground() {
    // some code
}
ekashking
  • 387
  • 6
  • 19
0
  1. Application class is implemented by LifecycleObserver
  2. take a static boolean variable for check application is in background or foreground
  3. check the state of application with the help of LifecycleEvent methods
class Application() : LifecycleObserver {

    companion object {
        var isAppInBackground: Boolean = true

    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onAppBackgrounded() {
        isAppInBackground = true
        Log.d(TAG, "background")
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onAppForegrounded() {
        isAppInBackground = false
        Log.d(TAG, "foreground")

    }
} 
Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
RanaUmer
  • 561
  • 5
  • 9
  • Well ... this is what I mean by the incomplete answer. I've seen it many times. But not a single step-by-step implementation. – ekashking Nov 11 '19 at 22:03
  • `@OnLifecycleEvent` is deprecated. https://developer.android.com/jetpack/androidx/releases/lifecycle#2.4.0-beta01 – Akito Nov 19 '21 at 15:15