How to detect when an Android app goes to the background and come back to the foreground

后端 未结 30 1348
独厮守ぢ
独厮守ぢ 2020-11-22 00:56

I am trying to write an app that does something specific when it is brought back to the foreground after some amount of time. Is there a way to detect when an app is sent to

相关标签:
30条回答
  • 2020-11-22 01:01

    This is pretty easy with ProcessLifecycleOwner

    Add these dependencies

    implementation "android.arch.lifecycle:extensions:$project.archLifecycleVersion"
    kapt "android.arch.lifecycle:compiler:$project.archLifecycleVersion"
    

    In Kotlin:

    class ForegroundBackgroundListener : LifecycleObserver {
    
    
        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        fun startSomething() {
            Log.v("ProcessLog", "APP IS ON FOREGROUND")
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        fun stopSomething() {
            Log.v("ProcessLog", "APP IS IN BACKGROUND")
        }
    }
    

    Then in your base activity:

    override fun onCreate() {
            super.onCreate()
    
            ProcessLifecycleOwner.get()
                    .lifecycle
                    .addObserver(
                            ForegroundBackgroundListener()
                                    .also { appObserver = it })
        }
    

    See my article on this topic: https://medium.com/@egek92/how-to-actually-detect-foreground-background-changes-in-your-android-application-without-wanting-9719cc822c48

    0 讨论(0)
  • 2020-11-22 01:04

    The onPause() and onResume() methods are called when the application is brought to the background and into the foreground again. However, they are also called when the application is started for the first time and before it is killed. You can read more in Activity.

    There isn't any direct approach to get the application status while in the background or foreground, but even I have faced this issue and found the solution with onWindowFocusChanged and onStop.

    For more details check here Android: Solution to detect when an Android app goes to the background and come back to the foreground without getRunningTasks or getRunningAppProcesses.

    0 讨论(0)
  • 2020-11-22 01:04

    I found a good method to detect application whether enter foreground or background. Here is my code. Hope this help you.

    /**
     * Custom Application which can detect application state of whether it enter
     * background or enter foreground.
     *
     * @reference http://www.vardhan-justlikethat.blogspot.sg/2014/02/android-solution-to-detect-when-android.html
     */
     public abstract class StatusApplication extends Application implements ActivityLifecycleCallbacks {
    
    public static final int STATE_UNKNOWN = 0x00;
    public static final int STATE_CREATED = 0x01;
    public static final int STATE_STARTED = 0x02;
    public static final int STATE_RESUMED = 0x03;
    public static final int STATE_PAUSED = 0x04;
    public static final int STATE_STOPPED = 0x05;
    public static final int STATE_DESTROYED = 0x06;
    
    private static final int FLAG_STATE_FOREGROUND = -1;
    private static final int FLAG_STATE_BACKGROUND = -2;
    
    private int mCurrentState = STATE_UNKNOWN;
    private int mStateFlag = FLAG_STATE_BACKGROUND;
    
    @Override
    public void onCreate() {
        super.onCreate();
        mCurrentState = STATE_UNKNOWN;
        registerActivityLifecycleCallbacks(this);
    }
    
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        // mCurrentState = STATE_CREATED;
    }
    
    @Override
    public void onActivityStarted(Activity activity) {
        if (mCurrentState == STATE_UNKNOWN || mCurrentState == STATE_STOPPED) {
            if (mStateFlag == FLAG_STATE_BACKGROUND) {
                applicationWillEnterForeground();
                mStateFlag = FLAG_STATE_FOREGROUND;
            }
        }
        mCurrentState = STATE_STARTED;
    
    }
    
    @Override
    public void onActivityResumed(Activity activity) {
        mCurrentState = STATE_RESUMED;
    
    }
    
    @Override
    public void onActivityPaused(Activity activity) {
        mCurrentState = STATE_PAUSED;
    
    }
    
    @Override
    public void onActivityStopped(Activity activity) {
        mCurrentState = STATE_STOPPED;
    
    }
    
    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    
    }
    
    @Override
    public void onActivityDestroyed(Activity activity) {
        mCurrentState = STATE_DESTROYED;
    }
    
    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
        if (mCurrentState == STATE_STOPPED && level >= TRIM_MEMORY_UI_HIDDEN) {
            if (mStateFlag == FLAG_STATE_FOREGROUND) {
                applicationDidEnterBackground();
                mStateFlag = FLAG_STATE_BACKGROUND;
            }
        }else if (mCurrentState == STATE_DESTROYED && level >= TRIM_MEMORY_UI_HIDDEN) {
            if (mStateFlag == FLAG_STATE_FOREGROUND) {
                applicationDidDestroyed();
                mStateFlag = FLAG_STATE_BACKGROUND;
            }
        }
    }
    
    /**
     * The method be called when the application been destroyed. But when the
     * device screen off,this method will not invoked.
     */
    protected abstract void applicationDidDestroyed();
    
    /**
     * The method be called when the application enter background. But when the
     * device screen off,this method will not invoked.
     */
    protected abstract void applicationDidEnterBackground();
    
    /**
     * The method be called when the application enter foreground.
     */
    protected abstract void applicationWillEnterForeground();
    

    }

    0 讨论(0)
  • 2020-11-22 01:05

    i know its a little late but i think all these answers do have some problems while i did it like below and that works perfect.

    create a activity life cycle callback like this:

     class ActivityLifeCycle implements ActivityLifecycleCallbacks{
    
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    
        }
    
        @Override
        public void onActivityStarted(Activity activity) {
    
        }
    
        Activity lastActivity;
        @Override
        public void onActivityResumed(Activity activity) {
            //if (null == lastActivity || (activity != null && activity == lastActivity)) //use this condition instead if you want to be informed also when  app has been killed or started for the first time
            if (activity != null && activity == lastActivity) 
            {
                Toast.makeText(MyApp.this, "NOW!", Toast.LENGTH_LONG).show();
            }
    
            lastActivity = activity;
        }
    
        @Override
        public void onActivityPaused(Activity activity) {
    
        }
    
        @Override
        public void onActivityStopped(Activity activity) {
    
        }
    
        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    
        }
    
        @Override
        public void onActivityDestroyed(Activity activity) {
    
        }
    }
    

    and just register it on your application class like below:

    public class MyApp extends Application {
    
    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifeCycle());
    }
    
    0 讨论(0)
  • 2020-11-22 01:06

    This appears to be one of the most complicated questions in Android since (as of this writing) Android doesn't have iOS equivalents of applicationDidEnterBackground() or applicationWillEnterForeground() callbacks. I used an AppState Library that was put together by @jenzz.

    [AppState is] a simple, reactive Android library based on RxJava that monitors app state changes. It notifies subscribers every time the app goes into background and comes back into foreground.

    It turned out this is exactly what I needed, especially because my app had multiple activities so simply checking onStart() or onStop() on an activity wasn't going to cut it.

    First I added these dependencies to gradle:

    dependencies {
        compile 'com.jenzz.appstate:appstate:3.0.1'
        compile 'com.jenzz.appstate:adapter-rxjava2:3.0.1'
    }
    

    Then it was a simple matter of adding these lines to an appropriate place in your code:

    //Note that this uses RxJava 2.x adapter. Check the referenced github site for other ways of using observable
    Observable<AppState> appState = RxAppStateMonitor.monitor(myApplication);
    //where myApplication is a subclass of android.app.Application
    appState.subscribe(new Consumer<AppState>() {
        @Override
        public void accept(@io.reactivex.annotations.NonNull AppState appState) throws Exception {
            switch (appState) {
                case FOREGROUND:
                    Log.i("info","App entered foreground");
                    break;
                case BACKGROUND:
                    Log.i("info","App entered background");
                    break;
            }
        }
    });
    

    Depending on how you subscribe to the observable, you may have to unsubscribe from it to avoid memory leaks. Again more info on the github page.

    0 讨论(0)
  • 2020-11-22 01:06

    Since I did not find any approach, which also handles rotation without checking time stamps, I thought I also share how we now do it in our app. The only addition to this answer https://stackoverflow.com/a/42679191/5119746 is, that we also take the orientation into consideration.

    class MyApplication : Application(), Application.ActivityLifecycleCallbacks {
    
       // Members
    
       private var mAppIsInBackground = false
       private var mCurrentOrientation: Int? = null
       private var mOrientationWasChanged = false
       private var mResumed = 0
       private var mPaused = 0
    

    Then, for the callbacks we have the resume first:

       // ActivityLifecycleCallbacks
    
       override fun onActivityResumed(activity: Activity?) {
    
          mResumed++
    
          if (mAppIsInBackground) {
    
             // !!! App came from background !!! Insert code
    
             mAppIsInBackground = false
          }
          mOrientationWasChanged = false
        }
    

    And onActivityStopped:

       override fun onActivityStopped(activity: Activity?) {
    
           if (mResumed == mPaused && !mOrientationWasChanged) {
    
           // !!! App moved to background !!! Insert code
    
            mAppIsInBackground = true
        }
    

    And then, here comes the addition: Checking for orientation changes:

       override fun onConfigurationChanged(newConfig: Configuration) {
    
           if (newConfig.orientation != mCurrentOrientation) {
               mCurrentOrientation = newConfig.orientation
               mOrientationWasChanged = true
           }
           super.onConfigurationChanged(newConfig)
       }
    

    That's it. Hope this helps someone :)

    0 讨论(0)
提交回复
热议问题