По моему мнению, многие ответы вводят большую нагрузку кода и приносят много сложности и нечитаемости.
Когда люди спрашивают на SO, как связаться между Service
и Activity
, я обычно советую использовать LocalBroadcastManager .
Почему?
Ну, цитируя документы:
Вы знаете, что передаваемые вами данные не покинут ваше приложение, поэтому вам не нужно беспокоиться о утечке личных данных.
Другие приложения не могут отправлять эти трансляции в ваше приложение, поэтому вам не нужно беспокоиться о наличии дыр в безопасности, которые они могут использовать.
Это более эффективно, чем отправка глобальной трансляции через систему.
Не в документах:
- Не требует внешних библиотек
- Код минимальный
- Это быстро реализовать и понять
- Нет пользовательских самореализованных обратных вызовов / ультра-синглтон / внутрипроцессный
шаблон вообще ...
- Нет сильных ссылок на
Activity
, Application
, ...
Описание
Итак, вы хотите проверить, находится ли какой-либо из Activity
в данный момент на переднем плане. Вы обычно делаете это в Service
или в вашем Application
классе.
Это означает, что ваши Activity
объекты становятся отправителями сигнала (я включен / я выключен). Ваш Service
, с другой стороны, становится Receiver
.
Есть два момента, в которые ваш Activity
сообщает вам, идет ли он на переднем плане или на заднем плане (да только два ... не 6).
Когда Activity
выходит на передний план, запускается метод onResume()
(также вызывается после onCreate()
).
Когда Activity
идет сзади, вызывается onPause()
.
Это моменты, когда ваш Activity
должен отправить сигнал вашему Service
, чтобы описать его состояние.
В случае нескольких Activity
, помните, что Activity
сначала уходит на задний план, затем еще один выходит на передний план.
Так что ситуация будет: *
Activity1 -- send --> Signal:OFF
Activity2 -- send --> Signal:ON
Service
/ Application
просто продолжит прослушивать эти сигналы и будет действовать соответственно.
Код (TLDR)
Ваш Service
должен реализовать BroadcastReceiver
для прослушивания сигналов.
this.localBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// received data if Activity is on / off
}
}
public static final IntentFilter SIGNAL_FILTER = new IntentFilter("com.you.yourapp.MY_SIGNAL")
Зарегистрируйте Receiver
в Service::onCreate()
@Override
protected void onCreate() {
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, SIGNAL_FILTER);
}
Отменить регистрацию в Service::onDestroy()
@Override
protected void onDestroy() {
// I'm dead, no need to listen to anything anymore.
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
}
Теперь ваши Activity
должны сообщить свое состояние.
В Activity::onResume()
Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put ON boolean in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
В Activity::onPause()
Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put OFF boolean in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
Очень, очень распространенная ситуация
Разработчик: Я хочу отправить данные с моего Service
и обновить Activity
. Как проверить, находится ли Activity
на переднем плане?
Обычно нет необходимости проверять, находится ли Activity
на переднем плане или нет. Просто отправьте данные через LocalBroadcastManager
с вашего Service
. Если Activity
включен, то он будет реагировать и действовать.
В этой очень распространенной ситуации Service
становится отправителем, а Activity
реализует BroadcastReceiver
.
Итак, создайте Receiver
в вашем Activity
. Зарегистрируйте его в onResume()
и отмените регистрацию в onPause()
. Нет необходимости использовать другие методы жизненного цикла .
Определите поведение Receiver
в onReceive()
(обновите ListView, сделайте это, сделайте это, ...).
Таким образом, Activity
будет слушать, только если он находится на переднем плане, и ничего не произойдет, если он находится сзади или уничтожен.
В случае нескольких Activity
, в зависимости от того, включен Activity
, будет ответ (если они также реализуют Receiver
).
Если все находятся на заднем плане, никто не ответит, и сигнал просто потеряется.
Отправьте данные из Service
через Intent
(см. Код выше), указав идентификатор сигнала.