问题 如何在BroadcastReceiver中知道App是否在前台运行?


我正在处理需要每晚进行同步的应用程序。我使用Alarm Manager在我想要的时刻调用BroadcastReceiver。问题是如果应用程序在前台运行以避免丢失数据,我就无法进行同步。所以我需要在Broadcast Receiver中知道应用程序是否在前台运行以取消此同步。

我尝试了在StackOverflow中找到的解决方案: 检查Android应用程序是否在后台运行  但是此参数在BroadcastReceiver中始终为false,但在activites中为true。

谁能告诉我哪个是问题?我做得不好?

真的感谢!


9002
2018-05-09 10:03


起源

告诉你更多关于“在前景中运行”的含义? - Richard Le Mesurier
你必须要显示你的代码... - Richard Le Mesurier


答案:


试试这种方式希望这适合你

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" />

13
2018-05-09 10:14



我试过这个解决方案,但总是返回true ... - pgarriga
启动应用程序 - >按主页按钮然后检查 - Biraj Zalavadia
嗨我更新答案尝试现在将100%工作 - Biraj Zalavadia
android.permission.GET_TASKS 现已弃用。 - Hussein El Feky
<uses-permission android:name =“android.permission.GET_TASKS”/>并且现在也弃用了getRunningTasks ...请更新答案。 - demo


“应用程序在前台运行”是什么意思?

如果你的意思是有一个 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 进行同步。否则系统可能会杀死你的应用程序 - 你不能在a中执行任何长时间运行的任务 BroadcastReceiver

因此,在启动同步服务之前,请检查应用程序布尔值以查看您的应用程序是否处于“前台”状态。或者,在同步服务中移动支票,这样做的好处就是 BroadcastReceiver 甚至更简单(我总是赞成尽量使接收器具有尽可能少的逻辑)。


该方法具有易于使用,理解并且不需要额外许可的优点。


2
2018-05-09 10:12



谢谢你的快速回答。就像我在我的问题中解释的那样,我按照你说的去做,但这个参数总是错误的,而Activity现在正在运行。这就是问题。而且,你是对的,我没有在BroadcastReceiver中进行同步。 - pgarriga
@PereGarriga更多地讲述你的意思是“在前台运行”? - Richard Le Mesurier
当活动显示时。 - pgarriga
@PereGarriga我唯一想到的就是把支票移出去 BroadcastReceiver 进入你的 Service,看看它是否还在 false 那里。 - Richard Le Mesurier


该方法会告诉您应用中的任何活动当前是否在前台。如果从广播接收器检查MyApplication.isActivityVisible()方法,则应该可以正常工作。如果它返回假,那么maybes没有活动  展示。


0
2018-05-09 10:13





如果你不想做任何事情,如果应用程序在前台你可以简单地关闭你的活动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
2017-07-05 08:42