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


当前回答

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"

其他回答

创建一个扩展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
        }
    }

如果你的应用由多个活动和/或堆叠的活动组成,就像一个标签栏小部件,那么覆盖onPause()和onResume()将不起作用。例如,当启动一个新的活动,当前的活动将得到暂停之前,新的一个被创建。当完成一个活动(使用“后退”按钮)时,也同样适用。

我发现有两种方法似乎很有效。

第一个需要GET_TASKS权限,由一个简单的方法组成,通过比较包名来检查设备上运行最多的活动是否属于应用程序:

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

    return false;
}

这种方法是在Droid-Fu(现在称为Ignition)框架中发现的。

我自己实现的第二个方法不需要GET_TASKS权限,这很好。相反,它的实现有点复杂。

在MainApplication类中,有一个变量用于跟踪应用程序中正在运行的活动的数量。在onResume()中为每个活动增加变量,在onPause()中减少变量。

当正在运行的activity数量达到0时,如果满足以下条件,应用程序将被放入后台:

正在暂停的活动没有结束(使用了“后退”按钮)。这可以通过使用activity.isFinishing()方法来完成。 没有启动一个新活动(相同的包名)。你可以重写startActivity()方法来设置一个变量来指示这一点,然后在onPostResume()中重置它,这是创建/恢复活动时运行的最后一个方法。

当您可以检测到应用程序已经退出到后台时,当它被带回前台时也很容易检测到。

LifecycleObserver已弃用。使用DefaultLifecycleObserver代替:

public class YourApplication extends Application implements DefaultLifecycleObserver {

    @Override
    public void onCreate() {
        super.onCreate();
        ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    }

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        DefaultLifecycleObserver.super.onStart(owner);
    }

    @Override
    public void onResume(@NonNull LifecycleOwner owner) {
        DefaultLifecycleObserver.super.onResume(owner);
    }

    @Override
    public void onPause(@NonNull LifecycleOwner owner) {
        DefaultLifecycleObserver.super.onPause(owner);
    }

    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        DefaultLifecycleObserver.super.onStop(owner);
    }

    @Override
    public void onDestroy(@NonNull LifecycleOwner owner) {
        DefaultLifecycleObserver.super.onDestroy(owner);
    }
}

依赖关系:

  implementation 'androidx.lifecycle:lifecycle-common:2.5.1'
  implementation 'androidx.lifecycle:lifecycle-process:2.5.1'

您可以在ActivityLifecycleCallbacks和ComponentCallbacks2的帮助下轻松实现这一点。

创建一个实现上述接口的类AppLifeCycleHandler。

package com.sample.app;

import android.app.Activity;
import android.app.Application;
import android.content.ComponentCallbacks2;
import android.content.res.Configuration;
import android.os.Bundle;

/**
 * Created by Naveen on 17/04/18
 */
public class AppLifeCycleHandler
    implements Application.ActivityLifecycleCallbacks, ComponentCallbacks2 {

  AppLifeCycleCallback appLifeCycleCallback;

  boolean appInForeground;

  public AppLifeCycleHandler(AppLifeCycleCallback appLifeCycleCallback) {
    this.appLifeCycleCallback = appLifeCycleCallback;
  }

  @Override
  public void onActivityResumed(Activity activity) {
    if (!appInForeground) {
      appInForeground = true;
      appLifeCycleCallback.onAppForeground();
    }
  }

  @Override
  public void onTrimMemory(int i) {
    if (i == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
      appInForeground = false;
      appLifeCycleCallback.onAppBackground();
    }
  }

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

  }

  @Override
  public void onActivityStarted(Activity activity) {

  }

  @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() {

  }

  interface AppLifeCycleCallback {

    void onAppBackground();

    void onAppForeground();
  }
}

在你的类中,当应用程序在前台和后台之间切换时,应用程序实现AppLifeCycleCallback来获得回调。如下图所示。

public class BaseApplication extends Application implements AppLifeCycleHandler.AppLifeCycleCallback{

    @Override
    public void onCreate() {
        super.onCreate();
        AppLifeCycleHandler appLifeCycleHandler = new AppLifeCycleHandler(this);
        registerActivityLifecycleCallbacks(appLifeCycleHandler);
        registerComponentCallbacks(appLifeCycleHandler);
    }

    @Override
    public void onAppBackground() {
        Log.d("LifecycleEvent", "onAppBackground");
    }

    @Override
    public void onAppForeground() {
        Log.d("LifecycleEvent", "onAppForeground");
    }
}

希望这能有所帮助。

编辑 作为替代方案,您现在可以使用生命周期感知的体系结构组件。

这些答案似乎不正确。当另一个活动开始和结束时,也会调用这些方法。你能做的是保留一个全局标志(是的,全局不好:),并在每次启动一个新活动时将其设置为true。在每个活动的onCreate中将其设置为false。然后,在onPause中检查这个标志。如果为假,你的应用就会进入后台,或者被杀死。