Это правильное поведение на самом деле.Каждый раз, когда вы получаете сообщение, система отправляет SMS-трансляцию.Поскольку ваше приложение в своем манифесте заявляет, что оно хочет получать такие широковещательные сообщения, каждый раз будет создаваться и выполняться новый экземпляр вашего BroadcastReceiver.
Если вы хотите выполнить получатель только в определенные моменты времени (в этом случае, когда ваше приложение находится на переднем плане) , вы должны динамически зарегистрировать и отменить его регистрацию в коде вместо манифеста, используя Context.registerReceiver()
и Context.unregisterReceiver()
,
Как это сделать в точности?
Вот краткий пример.Я предполагаю, что вы написали свой собственный класс, который расширяет BroadcastReceiver и обрабатывает вещи в onReceive()
.Имя этого класса в этом примере - SmsReceiver
, как в связанном учебном пособии.
Наша цель - получать широковещательные сообщения только тогда, когда одно действие находится на переднем плане, что означает, что у вас также должен быть один класс, который расширяется.Активность и отображает пользовательский интерфейс как обычное приложение.
Прежде всего нам нужен фактический экземпляр получателя в качестве члена класса.Добавьте что-то вроде этого в свой класс деятельности:
private SmsReceiver smsReceiver = new SmsReceiver();
Sidenote: На самом деле это одно из основных различий между регистрацией в манифесте и в коде:
- В коде вы сами создаете экземпляр получателя
- При регистрации в манифесте система генерирует экземпляры для вас в фоновом режиме
Хорошо, отлично.Теперь нам просто нужно зарегистрировать и отменить регистрацию этого получателя, когда активность выходит на первый план и выходит из него.Взгляните на диаграмму в классе Activity doc , методы каркаса, вызываемые в этих событиях: onResume()
и onPause()
.
Добавьте следующие строки в ваш метод onResume()
:
@Override
public void onResume() {
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
registerReceiver(smsReceiver, filter);
}
То, что мы здесь сделали, на самом деле довольно просто.Это код, эквивалентный тегу манифеста <receiver />
.Мы создали фильтр намерений с широковещательной передачей, который нам нравится получать, и регистрируем наш получатель в нем
Следующий шаг - отменить регистрацию в onPause()
.Опять же, либо добавьте эту строку, либо создайте onPause()
, если вы этого еще не сделали.
@Override
public void onPause() {
unregisterReceiver(smsReceiver);
}
Довольно просто - возьмите экземпляр нашего получателя и отмените его регистрацию, когда приложение собирается уйти в фоновый режим.И это все волшебство, все должно работать как задумано. Не забудьте удалить весь тег <receiver />
в манифесте, когда вы работаете с существующим кодом.В противном случае вы зарегистрируете свой приемник двумя способами.