Использование намерения широковещания / получателя широковещания для отправки сообщений из службы в деятельность - PullRequest
46 голосов
/ 02 сентября 2011

Итак, я понимаю (я думаю) о намерениях вещания и получения им сообщений.

Итак, теперь моя проблема / что я не могу решить, это как отправить сообщение из метода 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

Ответы [ 4 ]

70 голосов
/ 02 сентября 2011

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..., как в моем примере. Это помогает избежать ситуации, когда другие приложения или системные компоненты могут попытаться обработать его.

68 голосов
/ 02 сентября 2011

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

Сценарий A: только действие

Если вам нужно получать трансляцию только тогда, когда у вас есть активность на переднем плане, зарегистрируйте активность на BroadcastReceiver, используя registerReceiver(). Как указано @MisterSquonk, вы должны зарегистрировать получателя в onResume() и отменить его регистрацию в onPause().

Сценарий B: действие «Если на переднем плане», «Другое»; Заказанная трансляция

Если вы хотите, чтобы действие на переднем плане обрабатывало трансляцию, но вы хотите, чтобы что-то происходило, если это действие не на переднем плане (например, поднимите Notification), и трансляция является упорядоченной трансляцией (например, входящая SMS), тогда вы все равно будете использовать решение сценария A, но с более высоким приоритетом IntentFilter (см. setPriority()). Кроме того, вы должны зарегистрировать BroadcastReceiver через элемент <receiver> в манифесте с более низким приоритетом <intent-filter> для той же самой трансляции. В упражнении BroadcastReceiver позвоните по номеру abortBroadcast(), чтобы использовать событие и не дать ему достичь зарегистрированного манифеста BroadcastReceiver.

Сценарий C: действие «Если на переднем плане», «Другое»; Обычная трансляция

Если сценарий B почти подходит, но трансляция, которую вы слушаете, не является заказанной трансляцией, вам нужно начать со сценария B. Однако, если трансляция, которую оба приемника имеют в своих соответствующих фильтрах, будет одной из ваших, используя личную строку действия, как предложено @MisterSquonk. Кроме того, еще один BroadcastReceiver зарегистрирован в манифесте, чей <intent-filter> предназначен для реального вещания, которое вы слушаете. Этот получатель просто позвонит по номеру sendOrderedBroadcast(), чтобы отправить заказанное вещание, которое слушают другие получатели.

Сценарий D: деятельность независимо от переднего плана

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

Если, однако, вы уверены, что это не является частью вашей модели данных, вы можете реализовать Сценарий B или Сценарий C, а также вставить некоторую информацию в элемент статических данных. Ваши действия могут проверить этот элемент статических данных в onResume(), чтобы получить информацию о трансляции, когда они возвращаются на передний план.

Если вы думаете «но, что если мой процесс будет прерван между трансляцией и другими действиями, выходящими на первый план?», То ваша трансляция действительно обновляет вашу модель данных, в соответствии с открытием абзац этого сценария.

Если вы думаете «но я хочу обновить действие, выполняющее работу в фоновом режиме», то рассматриваемое действие прерывается. Деятельность никогда не должна делать работу в фоновом режиме. Эту работу следует делегировать какой-либо форме службы, и существует целый ряд связанных сценариев для передачи широковещательной рассылки в службу.

17 голосов
/ 04 марта 2015

Для трансляции намерений:

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);
8 голосов
/ 05 января 2015

Возможно, не относится к моменту ответа на вопрос, но теперь в пакете поддержки 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);
...