我试图写一个应用程序,做一些具体的时候,它被带回前台后一段时间。是否有一种方法可以检测应用程序是被发送到后台还是被带到前台?


当前回答

使用ProcessLifecycleOwner在Activity(或任何类)中从后台到前台检测app的示例。 当应用程序启动时,我缓存启动时间,然后在每个活动中,我将检查应用程序时间,以知道活动是否在第一时间启动或从后台启动

class MyApplication : Application(), LifecycleObserver {

    var appStartBeginTime: Long? = null

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

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onMoveToForeground() {
        Log.i("TAG", "onMoveToForeground")
        appStartBeginTime = System.currentTimeMillis()
    }
}

LoginActivity

class LoginActivity : AppCompatActivity() {
    var localAppStartBeginTime: Long? = null

    ...
    
    // Detect in onResume() instead of onStart because 
    // onMoveToForeground() in MyApplication will fired before onStart 
    override fun onResume() {
        super.onResume()
        if (isOpenedFirstTimeOrFromBackground()) {
            Log.i("TAG", "open first time or from background")

            // do something: eg, call API
        } else {
            Log.i("TAG", "on in another time")
        }
    }

    private fun isOpenedFirstTimeOrFromBackground(): Boolean {
        val globalStartBeginTime = (application as MyApplication).appStartBeginTime
        if (localAppStartBeginTime != globalStartBeginTime) {
            localAppStartBeginTime = globalStartBeginTime
            return true
        }
        return false
    }
}

安卓清单

<manifest ...>

    <application
        android:name=".MyApplication"
        ...>
            
    </application>

</manifest>

演示 https://github.com/PhanVanLinh/AndroidDetectAppFromBackgroundToForeground

其他回答

在你的应用程序中添加回调并检查根活动,如下所示:

@Override
public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
        @Override
        public void onActivityStopped(Activity activity) {
        }

        @Override
        public void onActivityStarted(Activity activity) {
        }

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

        @Override
        public void onActivityResumed(Activity activity) {
        }

        @Override
        public void onActivityPaused(Activity activity) {
        }

        @Override
        public void onActivityDestroyed(Activity activity) {
        }

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            if (activity.isTaskRoot() && !(activity instanceof YourSplashScreenActivity)) {
                Log.e(YourApp.TAG, "Reload defaults on restoring from background.");
                loadDefaults();
            }
        }
    });
}

我的解决方案受到@d60402的答案的启发,也依赖于一个时间窗口,但不使用定时器:

public abstract class BaseActivity extends ActionBarActivity {

  protected boolean wasInBackground = false;

  @Override
  protected void onStart() {
    super.onStart();
    wasInBackground = getApp().isInBackground;
    getApp().isInBackground = false;
    getApp().lastForegroundTransition = System.currentTimeMillis();
  }

  @Override
  protected void onStop() {
    super.onStop();
    if( 1500 < System.currentTimeMillis() - getApp().lastForegroundTransition )
      getApp().isInBackground = true;
  }

  protected SingletonApplication getApp(){
    return (SingletonApplication)getApplication();
  }
}

其中SingletonApplication是Application类的扩展:

public class SingletonApplication extends Application {
  public boolean isInBackground = false;
  public long lastForegroundTransition = 0;
}

有三种方法可以实现这一点:

单一活动架构 ActivityLifecycleCallback 生命周期观察者和进程生命周期所有者

我在这里写了一篇关于这个的详细文章。希望能有所帮助。

我使用这个解决方案: http://nathanael.hevenet.com/android-dev-detecting-when-your-app-is-in-the-background-across-activities/

简而言之——构建一个专门的服务,让每个活动向他报告每个生命周期事件,这个服务获得关于应用程序状态的信息。

很像@oldschool4664的解决方案,但在我看来更干净

由于我没有找到任何方法,它也处理旋转而不检查时间戳,我想我也分享我们现在如何在我们的应用程序中这样做。 对这个答案https://stackoverflow.com/a/42679191/5119746唯一的补充是,我们还考虑了方向。

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

然后,对于回调,我们首先有简历:

   // ActivityLifecycleCallbacks

   override fun onActivityResumed(activity: Activity?) {

      mResumed++

      if (mAppIsInBackground) {

         // !!! App came from background !!! Insert code

         mAppIsInBackground = false
      }
      mOrientationWasChanged = false
    }

和onActivityStopped:

   override fun onActivityStopped(activity: Activity?) {

       if (mResumed == mPaused && !mOrientationWasChanged) {

       // !!! App moved to background !!! Insert code

        mAppIsInBackground = true
    }

然后,这里是附加的:检查方向变化:

   override fun onConfigurationChanged(newConfig: Configuration) {

       if (newConfig.orientation != mCurrentOrientation) {
           mCurrentOrientation = newConfig.orientation
           mOrientationWasChanged = true
       }
       super.onConfigurationChanged(newConfig)
   }

就是这样。希望这能帮助到一些人:)