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


当前回答

您可以在应用程序类中简单地调用此方法

ProcessLifecycleOwner.get().getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
                Log.e(TAG, "onStateChanged: " + event.toString());
            }
        });

生命周期。事件将返回应用程序的状态

ON_CREATE
ON_START
ON_RESUME
ON_PAUSE
ON_STOP
ON_DESTROY
ON_ANY

当应用程序进入后台时,它将返回ON_PAUSE & ON_STOP 当应用程序进入前台时,将返回ON_START & ON_RESUME

其他回答

这似乎是Android中最复杂的问题之一,因为(在撰写本文时)Android没有iOS中等效的applicationDidEnterBackground()或applicationwillenter前台()回调。我使用了一个由@jenzz组合的AppState库。

[AppState]是一个基于RxJava的简单的响应式Android库,用于监控应用程序状态的变化。每当应用程序进入后台并返回前台时,它都会通知订阅者。

事实证明,这正是我所需要的,特别是因为我的应用程序有多个活动,所以简单地检查onStart()或onStop()对一个活动不会削减它。

首先,我将这些依赖项添加到gradle:

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

然后,将这些行添加到代码中适当的位置就很简单了:

//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;
        }
    }
});

根据你订阅可观察对象的方式,你可能不得不取消订阅以避免内存泄漏。更多信息再次在github页面。

下面是我解决这个问题的方法。它的工作前提是,在活动转换之间使用时间参考最有可能提供足够的证据来证明应用程序是否“背景化”。

首先,我使用了一个android.app.Application实例(让我们称它为MyApplication),它有一个Timer,一个TimerTask,一个常量来表示从一个活动过渡到另一个活动可以合理地花费的最大毫秒数(我用了一个2s的值),一个布尔值来指示应用程序是否“在后台”:

public class MyApplication extends Application {

    private Timer mActivityTransitionTimer;
    private TimerTask mActivityTransitionTimerTask;
    public boolean wasInBackground;
    private final long MAX_ACTIVITY_TRANSITION_TIME_MS = 2000;
    ...

应用程序还提供了两种方法来启动和停止定时器/任务:

public void startActivityTransitionTimer() {
    this.mActivityTransitionTimer = new Timer();
    this.mActivityTransitionTimerTask = new TimerTask() {
        public void run() {
            MyApplication.this.wasInBackground = true;
        }
    };

    this.mActivityTransitionTimer.schedule(mActivityTransitionTimerTask,
                                           MAX_ACTIVITY_TRANSITION_TIME_MS);
}

public void stopActivityTransitionTimer() {
    if (this.mActivityTransitionTimerTask != null) {
        this.mActivityTransitionTimerTask.cancel();
    }

    if (this.mActivityTransitionTimer != null) {
        this.mActivityTransitionTimer.cancel();
    }

    this.wasInBackground = false;
}

这个解决方案的最后一部分是从所有活动的onResume()和onPause()事件中添加对这些方法的调用,或者,最好是在所有具体活动继承的基础活动中:

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

    MyApplication myApp = (MyApplication)this.getApplication();
    if (myApp.wasInBackground)
    {
        //Do specific came-here-from-background code
    }

    myApp.stopActivityTransitionTimer();
}

@Override
public void onPause()
{
    super.onPause();
    ((MyApplication)this.getApplication()).startActivityTransitionTimer();
}

所以在这种情况下,当用户只是在你的应用程序的活动之间导航,离开活动的onPause()启动定时器,但几乎立即进入的新活动取消定时器之前,它可以达到最大过渡时间。wasInBackground也是假的。

另一方面,当一个Activity从启动器来到前台,设备被唤醒,结束电话呼叫等,更有可能是定时器任务在此事件之前执行,因此wasInBackground被设置为true。

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

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

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

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

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

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

正确答案

创建名为MyApp的类,如下所示:

public class MyApp implements Application.ActivityLifecycleCallbacks, ComponentCallbacks2 {

    private Context context;
    public void setContext(Context context)
    {
        this.context = context;
    }

    private boolean isInBackground = false;

    @Override
    public void onTrimMemory(final int level) {
        if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {


            isInBackground = true;
            Log.d("status = ","we are out");
        }
    }


    @Override
    public void onActivityCreated(Activity activity, Bundle bundle) {

    }

    @Override
    public void onActivityStarted(Activity activity) {

    }

    @Override
    public void onActivityResumed(Activity activity) {

        if(isInBackground){

            isInBackground = false;
            Log.d("status = ","we are in");
        }

    }

    @Override
    public void onActivityPaused(Activity activity) {

    }

    @Override
    public void onActivityStopped(Activity activity) {

    }

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

    }

    @Override
    public void onActivityDestroyed(Activity activity) {

    }

    @Override
    public void onConfigurationChanged(Configuration configuration) {

    }

    @Override
    public void onLowMemory() {

    }
}

然后,在你想要的任何地方(最好是在应用程序中启动的第一个活动),添加下面的代码:

MyApp myApp = new MyApp();
registerComponentCallbacks(myApp);
getApplication().registerActivityLifecycleCallbacks(myApp);

完成了!现在当应用程序在后台时,我们得到日志状态:我们退出 当我们进入app,我们得到log status,我们是out