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


当前回答

我在谷歌Analytics EasyTracker中使用了这个,它起作用了。可以将其扩展为使用简单整数来完成您想要的任务。

public class MainApplication extends Application {

    int isAppBackgrounded = 0;

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

    private void appBackgroundedDetector() {
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle bundle) {

            }

            @Override
            public void onActivityStarted(Activity activity) {
                EasyTracker.getInstance(MainApplication.this).activityStart(activity);
            }

            @Override
            public void onActivityResumed(Activity activity) {
                isAppBackgrounded++;
                if (isAppBackgrounded > 0) {
                    // Do something here
                }
            }

            @Override
            public void onActivityPaused(Activity activity) {
                isAppBackgrounded--;
            }

            @Override
            public void onActivityStopped(Activity activity) {
                EasyTracker.getInstance(MainApplication.this).activityStop(activity);
            }

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

            }

            @Override
            public void onActivityDestroyed(Activity activity) {

            }
        });
    }
}

其他回答

创建一个扩展Application的类。然后我们可以在其中使用它的重载方法onTrimMemory()。

为了检测应用程序是否进入了后台,我们将使用:

 @Override
    public void onTrimMemory(final int level) {
        if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { // Works for Activity
            // Get called every-time when application went to background.
        } 
        else if (level == ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { // Works for FragmentActivty
        }
    }

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

您可以使用ProcessLifecycleOwner将生命周期观察者附加到它。

  public class ForegroundLifecycleObserver implements LifecycleObserver {

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    public void onAppCreated() {
        Timber.d("onAppCreated() called");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onAppStarted() {
        Timber.d("onAppStarted() called");
    }

    @OnLifecycleEvent(Event.ON_RESUME)
    public void onAppResumed() {
        Timber.d("onAppResumed() called");
    }

    @OnLifecycleEvent(Event.ON_PAUSE)
    public void onAppPaused() {
        Timber.d("onAppPaused() called");
    }

    @OnLifecycleEvent(Event.ON_STOP)
    public void onAppStopped() {
        Timber.d("onAppStopped() called");
    }
}

然后在你的Application类的onCreate()你调用这个:

ProcessLifecycleOwner.get().getLifecycle().addObserver(new ForegroundLifecycleObserver());

有了它,你将能够捕捉应用程序在后台运行时发生的ON_PAUSE和ON_STOP事件。

The principal problem is that you have to get an specific behavior when you start an activity from background. If you override your onPause() and onResume() methods, you'll have a close answer, but not the solution. The problem is that onPause() and onResume() methods are called even if you don't minimize your application, they can be called when you start an activity and later you press the back button to return to your activity. To eliminate that problem and to know really when your application comes from background, you must to get the running process and compare with your process:

private boolean isApplicationBroughtToBackground() {
    ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> tasks = am.getRunningTasks(1);
    if (!tasks.isEmpty()) {
        ComponentName topActivity = tasks.get(0).topActivity;
        if (!topActivity.getPackageName().equals(getPackageName())) {
            return true;
        }
    }
    return false;
}

现在你必须声明一个布尔变量:

public boolean wasPaused = false;

并询问你的活动何时进入后台:

@Override
public void onPause(){
    super.onPause();
    if(isApplicationBroughtToBackground())
        wasPaused = true;
}

现在,当你的活动再次出现在屏幕上时,在onResume()方法中询问:

@Override
public void onResume(){
    super.onResume();
    if(wasPaused){
        lockScreen(true);
    }
    wasPaused = false;
}

就是这样。现在,当您的活动进入后台,稍后用户将其带到前台时,锁定屏幕将出现。

如果你想为你的应用程序的任何活动重复这个行为,你必须创建一个活动(可以是BaseActivity),放这个方法,你所有的活动都必须从BaseActivity继承。

我希望这对你有帮助。

问候!

我们用这个方法。它看起来太简单了,但它在我们的应用程序中经过了良好的测试,实际上在所有情况下都运行得非常好,包括通过“home”按钮进入主屏幕,通过“返回”按钮,或在屏幕锁定后返回主屏幕。试一试。

想法是,当在前景,Android总是开始新的活动之前停止前一个。这并不能保证,但这就是它的工作原理。顺便说一句,Flurry似乎使用了同样的逻辑(只是猜测,我没有检查,但它在相同的事件中挂钩)。

public abstract class BaseActivity extends Activity {

    private static int sessionDepth = 0;

    @Override
    protected void onStart() {
        super.onStart();       
        sessionDepth++;
        if(sessionDepth == 1){
        //app came to foreground;
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (sessionDepth > 0)
            sessionDepth--;
        if (sessionDepth == 0) {
            // app went to background
        }
    }

}

编辑:根据注释,我们也移动到onStart()在以后的版本的代码。此外,我还添加了超级调用,这是我最初的文章中所没有的,因为这更像是一个概念,而不是一个工作代码。