Использование трансляции/широковещательного приемника для отправки сообщений от службы к активности
Итак, я понимаю (я думаю) о намерениях трансляции и получая им сообщения.
Итак, моя проблема/то, что я не могу решить, - это отправить сообщение из метода onReceive
получателя в действие. Допустим, у меня есть приемник как таковой:
public class ReceiveMessages extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equalsIgnoreCase(TheService.DOWNLOADED)){
// send message to activity
}
}
}
Как отправить сообщение активности?
Должен ли я создать экземпляр получателя в действии, в котором я хочу отправить сообщения и каким-то образом отслеживать его? Или что? Я понимаю концепцию, но не приложение.
Любая помощь будет абсолютно потрясающей, спасибо.
Tom
Ответы
Ответ 1
EDITED Исправлены примеры кода для регистрации/отмены регистрации BroadcastReceiver
, а также удаления декларации манифеста.
Определите ReceiveMessages
как внутренний класс внутри Activity
, который должен прослушивать сообщения из Service
.
Затем объявите переменные класса, такие как...
ReceiveMessages myReceiver = null;
Boolean myReceiverIsRegistered = false;
В onCreate()
используйте myReceiver = new ReceiveMessages();
Тогда в onResume()
...
if (!myReceiverIsRegistered) {
registerReceiver(myReceiver, new IntentFilter("com.mycompany.myapp.SOME_MESSAGE"));
myReceiverIsRegistered = true;
}
... и в onPause()
...
if (myReceiverIsRegistered) {
unregisterReceiver(myReceiver);
myReceiverIsRegistered = false;
}
В Service
создайте и передайте Intent
...
Intent i = new Intent("com.mycompany.myapp.SOME_MESSAGE");
sendBroadcast(i);
И об этом. Сделайте "действие" уникальным для вашего пакета/приложения, т.е. com.mycompany...
, как в моем примере. Это помогает избежать ситуации, когда другие приложения или системные компоненты могут попытаться обработать его.
Ответ 2
Не обижайтесь, но ваш вопрос все еще проклят. Итак, я собираюсь изложить весь беспорядок сценариев и надеюсь, что один из них действительно ударит по любой проблеме, о которой вы думаете.
Сценарий A: Только активность
Если вам нужно только получать трансляцию, когда у вас есть активность на переднем плане, зарегистрируйте операцию BroadcastReceiver
с помощью registerReceiver()
. Как указано в @MisterSquonk, вы зарегистрируете приемник в onResume()
и отмените регистрацию в onPause()
.
Сценарий B: активность, если на переднем плане, другое другое; Заказная трансляция
Если вы хотите, чтобы активность переднего плана обрабатывала широковещательную рассылку, но вы хотите, чтобы что-то еще произошло, если это действие не находится на переднем плане (например, поднять Notification
), а широковещательная передача - упорядоченная трансляция (например, входящая SMS), то вы все равно будете использовать решение Scenario A, но с более высоким приоритетом IntentFilter
(см. setPriority()
). Кроме того, вы зарегистрировали бы BroadcastReceiver
через элемент <receiver>
в манифесте с более низким приоритетом <intent-filter>
для той же широковещательной передачи. В действии BroadcastReceiver
вызовите abortBroadcast()
, чтобы использовать это событие и не допустить его доступа к зарегистрированному манифестам BroadcastReceiver
.
Сценарий C: действие, если на переднем плане, другое другое; Регулярное вещание
Если сценарий B почти подходит, но широковещательная передача, которую вы слушаете, не является упорядоченной трансляцией, вам нужно будет начать с сценария B. Однако иметь трансляцию, которую оба приемника имеют в своих фильтрах, являются вашими собственными, используя частную строку действий, предложенную @MisterSquonk. Кроме того, в манифесте зарегистрирован еще один BroadcastReceiver
, чей <intent-filter>
предназначен для реальной трансляции, которую вы слушаете. Этот приемник просто вызывал sendOrderedBroadcast()
для отправки упорядоченной трансляции, которую прослушивают другие приемники.
Сценарий D: активность независимо от переднего плана
Если какая-либо ваша деятельность должна знать о трансляции, и не имеет значения, находится ли она на переднем плане, вам нужно переосмыслить, что вы подразумеваете под этим. Обычно это означает, что трансляция влияет на вашу модель данных каким-то образом, и в этом случае ваша озабоченность не должна состоять в том, чтобы сообщить об этом деятельности, а скорее обновить вашу модель данных и использовать уже существующую "пусть действия знают о изменение модели данных" логики обрабатывают остальные.
Если, однако, вы уверены, что это не часть вашей модели данных, вы можете реализовать сценарий B или сценарий C, а также добавить некоторую информацию в статическом члене данных. Ваши действия могут проверить, что статический член данных в onResume()
, чтобы получить информацию о трансляции, когда они возвращаются на передний план.
Если вы думаете "но, что, если мой процесс завершен между трансляцией и другим действием, выходящим на передний план?", тогда ваша трансляция действительно обновляет вашу модель данных, за открывающий абзац этого сценария.
Если вы думаете: "Но я хочу обновить действие, которое выполняет работу в фоновом режиме", тогда рассматриваемая деятельность нарушена. Действия никогда не должны делать работу в фоновом режиме. Эта работа должна быть делегирована какой-либо форме обслуживания, а также имеется целый набор сценариев для получения широковещательной передачи для этой службы.
Ответ 3
Чтобы транслировать намерение:
Intent intent = new Intent("com.yourcompany.testIntent");
intent.putExtra("value","test");
sendBroadcast(intent);
Для получения того же намерения используйте:
IntentFilter filter = new IntentFilter("com.yourcompany.testIntent");
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String value = intent.getExtras().getString("value");
}
};
registerReceiver(receiver, filter);
Ответ 4
Возможно, это не актуально во время вопроса, но в пакете поддержки Android есть LocalBroadcastManager.
Работает практически так же, как и обычные трансляции, но всякая "болтовня" локальна для приложения, в котором он запущен.
Преимущества:
- Вы знаете, что данные, которые вы передаете, не покидают ваше приложение, поэтому вам не нужно беспокоиться о утечке конфиденциальных данных.
- Другие приложения не могут отправлять эти трансляции в ваше приложение, поэтому вам не нужно беспокоиться о наличии дыр в безопасности, которые они могут использовать.
- Это более эффективно, чем отправка глобальной широковещательной передачи через систему.
Пример:
Intent i = new Intent("my.local.intent");
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
и получить
receiver = new MyBroadcastReceiverToHandleLocalBroadcast();
IntentFilter i = new IntentFilter();
i.addAction("my.local.intent");
LocalBroadcastManager.getInstance(context).registerReceiver(receiver, i);