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


当前回答

这里有一个解决方案,通过使用deboning逻辑,确保我们不会得到连续的背景/前景事件。所以,它总是反映一种稳定的背景/前景状态。

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import java.util.Timer
import java.util.TimerTask

/**
 * An observer class to listen on the app's lifecycle.
 */
class AppLifecycleObserver(
    private val onAppGoesToBackground: () -> Unit = {},
    private val onAppEntersForeground: () -> Unit = {}
) : LifecycleEventObserver {

    private val debounce = DebouncingTimer(timeout = 10)

    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        debounce.refresh {
            when (event.targetState) {
                Lifecycle.State.CREATED -> onAppGoesToBackground()
                Lifecycle.State.RESUMED -> onAppEntersForeground()
                else -> Unit
            }
        }
    }

    fun attach() {
        ProcessLifecycleOwner.get().lifecycle.addObserver(this)
    }

    fun detach() {
        ProcessLifecycleOwner.get().lifecycle.removeObserver(this)
    }

    private class DebouncingTimer(private val timeout: Long) {

        private var timer: Timer? = null

        fun refresh(job: () -> Unit) {
            timer?.cancel()
            timer = Timer()
            timer?.schedule(object : TimerTask() {
                override fun run() = job.invoke()
            }, timeout)
        }
    }
}

只需要创建一个AppLifecycleObserver实例:

private val appLifecycleObserver = AppLifecycleObserver(
        onAppGoesToBackground = { // do whatever... },
        onAppEntersForeground = { // do whatever... }
    )
// Attach the observer when it is needed:
appLifecycleObserver.attach()

// Remove when there is no need to it:
appLifecycleObserver.detach()

不要忘记添加一个合适的依赖版本:

implementation("androidx.lifecycle:lifecycle-process:$lifecycle_version")

其他回答

我在Github app- prospect -background-listen上创建了一个项目

为应用程序中的所有Activity创建一个BaseActivity。

public class BaseActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    }

    public static boolean isAppInFg = false;
    public static boolean isScrInFg = false;
    public static boolean isChangeScrFg = false;

    @Override
    protected void onStart() {
        if (!isAppInFg) {
            isAppInFg = true;
            isChangeScrFg = false;
            onAppStart();
        }
        else {
            isChangeScrFg = true;
        }
        isScrInFg = true;

        super.onStart();
    }

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

        if (!isScrInFg || !isChangeScrFg) {
            isAppInFg = false;
            onAppPause();
        }
        isScrInFg = false;
    }

    public void onAppStart() {

        // Remove this toast
        Toast.makeText(getApplicationContext(), "App in foreground",    Toast.LENGTH_LONG).show();

        // Your code
    }

    public void onAppPause() {

        // Remove this toast
        Toast.makeText(getApplicationContext(), "App in background",  Toast.LENGTH_LONG).show();

        // Your code
    }
}

现在使用这个BaseActivity作为一个超类的所有你的活动像MainActivity扩展BaseActivity和onAppStart将被调用时,你启动你的应用程序和onappause()将被调用时,应用程序从后台从任何屏幕。

您可以使用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事件。

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

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

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

我设法监控应用导航到后台和回前台通过实现一个BaseActivity,利用onResume, onPause和onStop活动回调的使用。这是我的实现。

override fun onResume() {
    super.onResume()
    if (AppActivityState.state == AppState.ON_LAUNCHED) {
        // We are in the first launch.
        onLaunched()
    } else {
        if (AppActivityState.state == AppState.ON_BACKGROUND) {
            // We came from background to foreground.
            AppActivityState.state = AppState.ON_FOREGROUND
            onForeground()
        } else {
            // We are just navigating through pages.
            AppActivityState.state = AppState.RESUMED
        }
    }
}

override fun onPause() {
    super.onPause()
    // If state is followed by onStop then it means we will going to background.
    AppActivityState.state = AppState.PAUSED
}

override fun onStop() {
    super.onStop()

    // App will go to background base on the 'pause' cue.
    if (AppActivityState.state == AppState.PAUSED) {
        AppActivityState.state = AppState.ON_BACKGROUND
        onBackground()
    }
}

在创建BaseActivity之后,你只需要将这个activity扩展到应用程序中的任何activity。

在这些类型的实现中,您可以准确地检测到以下内容: onBackground >应用程序将进入后台 onForeground >应用将返回前台 onLaunch >应用程序刚刚打开

我希望这对你有帮助:)

我喜欢ProcessLifecycleOwner方法,但实际上可以跳过所有这些,因为在Activity的onCreate()方法中,可以很容易地确定它是第一次运行还是后续运行:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState == null) {
        /* savedInstanceState is always null on first run */
    } else {
        /* it's a subsequent run */
    }
}