Пишу модуль, отправляющий сообщения. Модуль, над которым я работаю, создает намерение, и при получении сообщения о статусе отправляет событие в RN:
Сообщения отправляются правильно, и событие отправляется в RN, но при каждом последующем вызове оно запускается для всех ранее отправленных сообщений. Таким образом, для первого вызова он вызывается один раз, для второго - дважды и так далее.
Вот что я использую для трансляции в RN:
private void sendEvent(String messageId) {
WritableMap params = Arguments.createMap();
params.putString("id", messageId);
this.reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit("info", params);
}
Вот как я вызываю намерение:
Random generator = new Random();
Intent sentIntent = new Intent(SENT);
sentIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent sentPI = PendingIntent.getBroadcast(reactContext, generator.nextInt(),
sentIntent, PendingIntent.FLAG_CANCEL_CURRENT);
reactContext.registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive(Context arg0, Intent arg1) {
sendEvent(messageId);
}
}, new IntentFilter(SENT));
Как видите, я уже пытаюсь установить флаги, которые не будут использовать намерение после исходного вызова. Как я могу заставить его выполнить намерение один раз и после отправки / получения сообщения отменить любые будущие звонки?
Спасибо за ваш ответ. Это мне очень помогло! Я указываю в качестве имени фильтра идентификатор интересующего меня сообщения. После получения отчета о доставке я отменяю подписку с помощью unregisterReceiver. Не могли бы вы сформулировать это в качестве ответа? Я хочу, чтобы вы получили за это должное. Еще раз спасибо!
Ах да, это еще один вариант. Я не думал об этом. Хороший. Я собираюсь ответить здесь чуть позже. Спасибо. Рад, что у тебя все получилось. Ваше здоровье!
Экземпляры BroadcastReceiver будут оставаться зарегистрированными до тех пор, пока вы явно не отмените их регистрацию (или пока регистрирующий Context не будет уничтожен). В этом случае вы создаете и регистрируете новый экземпляр для каждой отправки, но никогда не отменяете регистрацию ни одного из них. Поскольку широковещательный Intent всегда один и тот же, после первого сообщения каждое последующее сообщение будет запускать не только свой новый зарегистрированный экземпляр, но также каждый экземпляр, зарегистрированный ранее.
Для этого есть несколько разных решений.
Однократная регистрация только одного экземпляра Receiver перед началом любых отправок и отмена его регистрации после их завершения. Затем конкретные результаты сообщений можно было бы различить с помощью дополнительных функций на Intent. При реализации этой опции убедитесь, что отдельные PendingIntent созданы для каждого, указав уникальный requestCode - второй аргумент в getBroadcast() - для каждого из них.
Продолжайте регистрировать новый экземпляр для каждой отправки и отмените регистрацию в onReceive(). Здесь также можно использовать дополнительный компонент на Intent, чтобы гарантировать, что правильный экземпляр действует в данной трансляции, а затем соответствующим образом отменяет регистрацию. Опять же, убедитесь, что каждый раз используются разные PendingIntent.
Как упомянуто OP, аналогично второму подходу, продолжайте использовать отдельные экземпляры для каждой отправки, но используйте разные действия String для каждого; например, добавив идентификатор к базовому действию. Поскольку тогда Intent будут по своей сути неравными, PendingIntent уже будут отличаться, и уникальный requestCode не нужен.
Привет, Майк! Это не часть вопроса, но можем ли мы зарегистрировать два приемника с одинаковым контекстом реакции, например, IntentFilter filter = new IntentFilter (BluetoothAdapter.ACTION_STATE_CHANGED); reactContext.registerReceiver (mReceiver, фильтр); IntentFilter filter2 = новый IntentFilter (BluetoothAdapter.ANOTHER_ACTION); reactContext.registerReceiver (mReceiver2, filter2);
Похоже, вы регистрируете новый экземпляр Receiver каждый раз, когда отправляете, но вы нигде не отменяете его регистрацию, поэтому каждое последующее сообщение после первого будет запускать Receiver для каждого зарегистрированного перед ним. Вы можете просто
unregisterReceiver(this)вonReceive(), но это довольно наивный подход. В идеале вы бы прикрепили кIntentдополнительные устройства, чтобы убедиться, что вы отменяете регистрацию нужного. В качестве альтернативы вы можете зарегистрировать один экземпляр Receiver перед всеми отправками и отменить регистрацию только после завершения всех отправок.