如何检测安卓应用程序何时进入后台并返回前台

450

我正在尝试编写一个应用程序,在一段时间后恢复到前台时会执行特定操作。是否有一种方法可以检测应用程序何时被发送到后台或恢复到前台?


3
可以在问题中添加一个使用案例,因为它似乎不太明显,所以答案中没有涉及到。该应用程序可以启动另一个应用程序(例如相册),该应用程序仍将驻留在同一堆栈中并显示为应用程序的一个屏幕,然后按Home按钮。所有依赖于应用程序生命周期(甚至是内存管理)的方法都无法检测到这一点。它们将在外部活动出现时触发后台状态,而不是在按Home键时触发。 - Dennis K
这就是你要找的答案:https://dev59.com/OG855IYBdhLWcg3wUSgW#42679191 - Fred Porciúncula
1
请参考Google解决方案:https://dev59.com/KHA65IYBdhLWcg3wuhIR#48767617 - StepanM
45个回答

0

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


我没有谈论数据库...你是什么意思? - Joris Weimar
我支持你的答案。尽管我们可以在暂停调用时将该标志值保存在数据库中,但这并不是一个好的解决方案。 - Sandeep P

0

我成功地通过实现一个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之后,您只需将此活动扩展到应用程序中的任何活动即可。
在这些类型的实现中,您可以准确地检测以下内容: - onBackground > 应用程序将进入后台 - onForeground > 应用程序将返回前台 - onLaunch > 应用程序刚刚打开
希望这能对您有所帮助 :)

0
这个解决方案怎么样?
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();
        }
    }
}

所有活动都需要扩展BaseActivity。

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

当用户按下主页按钮或在应用程序之间切换时,只会调用onStop(),然后currentAct等于getLocalClassName()。


-1

-3
主要问题是当你从后台启动一个活动时,你必须获得特定的行为。如果你重写了你的onPause()和onResume()方法,你会得到一个接近的答案,但不是解决方案。问题在于,即使你没有最小化你的应用程序,onPause()和onResume()方法也会被调用,它们可能会在你启动一个活动后被调用,然后你按返回按钮返回到你的活动。为了消除这个问题,并真正知道你的应用程序何时从后台回来,你必须获取运行过程并与你的进程进行比较:
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。

我希望这对您有所帮助。

问候!


4
如本页面其他地方所述,getRunningTasks() 不适用于生产代码,并且显然,一些应用因使用它而被下架。 - Nate

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接