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

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

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

Как бы я отправил сообщение на активность?

Должен ли я создавать экземпляр получателя в активности, на которую я хочу отправлять сообщения, и каким-то образом отслеживать его? Или что? Я понимаю концепцию, но не совсем приложение.

Любая помощь была бы просто потрясающей, спасибо.

Том

4 ответа

Решение

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

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

Сценарий 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() забрать информацию о трансляции, когда они возвращаются на передний план.

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

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

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

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);

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