Как определить, является ли одно из моих действий на переднем плане

Я реализовал BroadcastReceiver, который запускается AlarmManager. AlarmManager инициализируется на BOOT_COMPLETED. Поэтому я должен объявить получателя в манифесте.

Моя проблема в том, что я хочу, чтобы BroadcastReceiver только что-то делал, когда ни один из моих собственных действий не был на переднем плане (иначе пользователь не взаимодействует с моим приложением). Я извлекаю информацию с удаленного сервера и не хочу уведомлять пользователя, если он в настоящее время находится в моем приложении.

Пока мне не удалось найти способ определить, находится ли мое приложение на переднем плане. Есть ли способ сделать такое? ActivityManager сообщает мне, работает ли мое приложение, но не находится ли оно на переднем плане.

Проблема почти такая же, как описано здесь: Информировать активность из BroadcastReceiver ТОЛЬКО, если она находится на переднем плане

РЕШЕНИЕ:

После оценки нескольких решений я хочу быстро наметить, что, по моему мнению, лучший метод для работы с фоном/передним планом.

Предпочтительный способ - зарегистрировать широковещательный приемник в методе onResume вашей деятельности и отменить его на действия onPause. Любая служба или другой фоновый элемент не будет нуждаться в отправке намерения трансляции с определенным действием, которое ваша деятельность будет перехватывать.

Если ваша деятельность находится на переднем плане, у нее будет зарегистрирован приемник намерения, и он сможет напрямую связать с отправкой цели с вашей службы. Если он не находится на переднем плане, он не получит намерения, но служба, которая вызвала трансляцию, будет знать, что никто не перехватил ее трансляцию и не сможет справиться с ней. Например, он может запускать желаемую активность, показывать уведомление и т.д.

Ответ 1

Следующий ответ: "работает ли приложение в фоновом режиме", суммирует решения, доступные для проверки фона/переднего плана.

Примечание:
Ранее этот ответ предлагал использовать ActivityManager.getRunningAppProcesses(), однако этот метод оказался не полностью надежным и его использование не поощрялось. Подробнее см. Ссылку выше.

Ответ 2

Ваша деятельность может отслеживать его собственное состояние относительно того, находится ли она на переднем плане (задано значение boolean на true в onStart(), на false в onStop()). Увы, это логическое не предоставляется вам Activity автоматически.

Ответ 3

ActivityManager#getRunningAppProcesses() возвращает список RunningAppProcessInfo. Каждое RunningAppProcessInfo имеет поле, называемое значением. значение, равное RunningAppProcessInfo.IMPORTANCE_FOREGROUND, похоже, показывает, какая активность активно наблюдается пользователем. Существует также RunningAppProcessInfo.IMPORTANCE_VISIBLE, который ниже, но может стоить проверить.

Ответ 4

проверить мое решение для определения того, находится ли действие на переднем плане: http://www.mannaz.at/codebase/android-activity-foreground-surveillance/

Это должно быть легко вернуть логику с "на переднем плане" на "не на переднем плане".

Ответ 5

Я реализовал BroadcastReceiver, который запускается AlarmManager. AlarmManager инициализируется на BOOT_COMPLETED. Поэтому я должен объявить получателя в манифесте.

Моя проблема в том, что я хочу, чтобы BroadcastReceiver только что-то делал, когда ни один из моих собственных действий не был на переднем плане (иначе пользователь не взаимодействует с моим приложением). Я извлекаю информацию с удаленного сервера и не хочу уведомлять пользователя, если он в настоящее время находится в моем приложении.

Пока мне не удалось найти способ определить, находится ли мое приложение на переднем плане. Есть ли способ сделать такое? ActivityManager сообщает мне, работает ли мое приложение, но не находится ли оно на переднем плане.

Кажется, что нет прямого способа определить, является ли одно из ваших действий текущим действием переднего плана. Тем не менее, вы можете получить желаемый эффект, используя упорядоченную трансляцию и два широковещательных приемника. Один широковещательный приемник должен быть зарегистрирован в OnResume() и незарегистрирован в OnPause(). Второй широковещательный приемник будет объявлен в вашем манифесте, как вы уже сделали. Установите приоритет для Android: приоритет для ваших приемников, чтобы, если зарегистрирован динамически зарегистрированный приемник, он сначала получит намерение, затем вы можете съесть намерение, чтобы получатель вещания, зарегистрированный в вашем манифесте, никогда не был уведомлен.

Ответ 7

Я бы использовал ActivityLifecycleCallbacks, чтобы получить более чистое решение.

Он может быть не уверен, прочитайте этот, прежде чем вы решите использовать приведенный ниже пример на производстве. Он работает в "домашней разработке" для моего устройства и версии ОС.

public class App extends Application implements Application.ActivityLifecycleCallbacks {

private boolean inForeground;

@Override
public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(this);
}

@Override
public void onActivityResumed(Activity activity) {
    inForeground = activity instanceof YourActivity;
}

public boolean isInForeground() {
    return inForeground;
}

Зарегистрируйте App в AndroidManifest:

<application
        android:name=".App" />

И последний кусок головоломки:

public class YourReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        App app = (App) context.getApplicationContext();
        if(app.isInForeground()){
            // do some stuff
        }
    }
}