如何在广播接收器中判断应用程序是否在前台运行?

15
我正在开发一个应用程序,需要每晚进行同步。我使用Alarm Manager在指定时间调用BroadcastReceiver。问题是,如果应用程序在前台运行,我无法进行同步以避免数据丢失。因此,我需要在Broadcast Receiver中知道应用程序是否在前台运行,以取消此同步。
我尝试了在StackOverflow找到的解决方案:检查Android应用程序是否在后台运行,但是这个参数在BroadcastReceiver中始终为false,在活动中却为true。
请问有人可以告诉我问题出在哪里吗?我做错了什么吗?
非常感谢!

能否稍微详细地说明一下“在前台运行”是什么意思? - Richard Le Mesurier
你需要展示你的代码,请。 - Richard Le Mesurier
4个回答

13

试试这种方式,希望对你有用。

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        if (isAppForground(context)) {
            // App is in Foreground
        } else {
            // App is in Background
        }
    }

    public boolean isAppForground(Context mContext) {

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

        return true;
    }

}

添加此权限

<uses-permission android:name="android.permission.GET_TASKS" />

启动应用程序 -> 按下主页按钮,然后检查。 - Biraj Zalavadia
3
android.permission.GET_TASKS 现已被弃用。 - Hussein El Feky
2
<uses-permission android:name="android.permission.GET_TASKS" /> 这个权限现在已经过时了,请更新答案。同时,getRunningTasks方法也已经过时了,请注意更新。 - demo

4
“应用正在前台运行”是什么意思呢?如果指当前有一个Activity正在屏幕上显示,那么最简单的方法就是创建一个基础的Activity类,并在您的“Application”类中设置一个全局布尔值。自定义“Application”类:
public class MyApp extends Application
{
    public boolean isInForeground = false;
}

定制基础Activity类:

abstract public class ABaseActivity extends Activity
{

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

        ((MyApp)getApplication()).isInForeground = true;
    }

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

        ((MyApp)getApplication()).isInForeground = false;
    }
}

我假设您没有在BroadcastReceiver中进行同步 - 您应该启动一个Service来执行同步。否则,系统可能会终止您的应用程序 - 您不能在BroadcastReceiver中执行任何长时间运行的任务。
因此,在启动同步服务之前,请检查应用程序布尔值以查看您的应用程序是否处于“前台”。或者将检查移至同步服务内部,这样可以使BroadcastReceiver更简单(我始终支持尽可能使接收器具有尽可能少的逻辑)。
使用此方法的优点是它简单易用,易于理解,并且不需要额外的权限。

1
感谢您的快速回复。就像我在问题中解释的那样,我做了您所说的,但是这个参数总是false而Activity正在运行。这就是问题所在。 而且,您说得对,我没有在BroadcastReceiver中进行同步。 - pgarriga
@PereGarriga 能否多讲一些您所说的“在前台运行”的意思? - Richard Le Mesurier
@PereGarriga 我能想到的唯一办法就是将检查从 BroadcastReceiver 移动到你的 Service 中,看看那里是否仍然为 false - Richard Le Mesurier

2

如果您不希望在应用程序在前台时执行任何操作,您可以在onStart方法中关闭活动接收器:

ComponentName receiver = new ComponentName(context, MyReceiver.class);
context.getPackageManager().setComponentEnabledSetting(receiver,
        PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
        PackageManager.DONT_KILL_APP);

您可以在“onStop”方法中将其打开:
ComponentName receiver = new ComponentName(context, MyReceiver.class);
context.getPackageManager().setComponentEnabledSetting(receiver,
        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
        PackageManager.DONT_KILL_APP);

如果接收器关闭了,就不会有任何警报传递到它,你的代码也不会被执行。

0

该方法可以告诉您应用程序中是否有任何活动处于前台。如果您从广播接收器检查MyApplication.isActivityVisible()方法,那么应该可以正常工作。如果它返回false,则可能没有任何活动正在显示。


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