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


当前回答

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

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

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

其他回答

2021年11月更新

实际设置如下

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleListener())
    }
}

class AppLifecycleListener : DefaultLifecycleObserver {

    override fun onStart(owner: LifecycleOwner) { // app moved to foreground
    }

    override fun onStop(owner: LifecycleOwner) { // app moved to background
    }
}

依赖关系

implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common:$lifecycle_version"

原来的答案

ProcessLifecycleOwner似乎也是一个很有前途的解决方案。

ProcessLifecycleOwner将分派ON_START, ON_RESUME事件,当第一个活动通过这些事件时。ON_PAUSE, ON_STOP,事件将在最后一个活动通过它们后延迟分派。这个延迟足够长,可以保证ProcessLifecycleOwner在由于配置更改而销毁和重新创建活动时不会发送任何事件。

实现可以简单到

class AppLifecycleListener : LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    fun onMoveToForeground() { // app moved to foreground
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onMoveToBackground() { // app moved to background
    }
}

// register observer
ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleListener())

根据源代码,当前延迟值为700ms。

使用此特性还需要依赖项:

implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleVersion"

onPause()和onResume()方法在应用程序被带到后台并再次进入前台时被调用。但是,在应用程序第一次启动时和关闭之前也会调用它们。你可以在活动中阅读更多。

没有任何直接的方法来获得应用程序的状态,而在后台或前台,但即使我已经面临这个问题,并找到解决方案与onWindowFocusChanged和onStop。

更多细节请查看这里Android:解决方案检测当一个Android应用程序去后台,回到前台没有getRunningTasks或getRunningAppProcesses。

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

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

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

这个解决方案呢

public class BaseActivity extends Activity
{

    static String currentAct = "";

    @Override
    protected void onStart()
    {
        super.onStart();

        if (currentAct.equals(""))
            Toast.makeText(this, "Start", Toast.LENGTH_LONG).show();

        currentAct = getLocalClassName();
    }

    @Override
    protected void onStop()
    {
        super.onStop();

        if (currentAct.equals(getLocalClassName()))
        {
            currentAct = "";
            Toast.makeText(this, "Stop", Toast.LENGTH_LONG).show();
        }
    }
}

所有的Activity都需要扩展BaseActivity。

当一个活动调用另一个(A->B)时,currentAct不等于getLocalClassName(),因为第二个活动(B)的onStart()在第一个(A) (https://developer.android.com/guide/components/activities.html#CoordinatingActivities)的onStop()之前被调用。

当用户按下home键或应用程序之间的变化将只调用onStop(),然后currentAct等于getLocalClassName()。

我的解决方案受到@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;
}