Adam
Adam

Reputation: 3518

ReactNative Android BroadcastReceiver Intent called multiple times

I am writing module that sends messages. Module I am working on creates intent and upon message received status emits event to RN:

Messages are sent correctly and event is emitted to RN, but on each consequent call, it triggers for all previously sent messages. So for first invoke it is called once, for the second twice and so on.

Here is what I use to broadcast to RN:

private void sendEvent(String messageId) {
        WritableMap params = Arguments.createMap();
        params.putString("id", messageId);
        this.reactContext
                .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit("info", params);
    }

Here is how I am invoking the intent:

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

As you can see I am already trying to set flags that would not use the Intent after original call. How can I make it to perform the intent once and upon sending/receiving of message cancel any future calls?

Upvotes: 2

Views: 2742

Answers (1)

Mike M.
Mike M.

Reputation: 39181

BroadcastReceiver instances will remain registered until you explicitly unregister them (or the registering Context is destroyed). In this case, you're creating and registering a new instance for each send, but never unregistering any of them. Since the broadcast Intent is always the same, after the first message, each subsequent message is going to fire not only its own newly registered instance, but also each instance registered previously.

There are a few different solutions for this.

  • Registering only a single Receiver instance once, before any sends begin, and unregistering it after they're all complete. The particular message results could then be distinguished by extras on the Intent. If implementing this option, be sure that distinct PendingIntents are created for each, by specifying a unique requestCode – the second argument in getBroadcast() – for each one.

  • Continue registering a new instance for each send, and unregister it in onReceive(). An extra on the Intent can be used here also, to ensure that the correct instance is acting on a given broadcast, and is appropriately unregistered afterwards. Again, be sure that distinct PendingIntents are used each time.

  • As mentioned by the OP, similar to the second approach, continue using separate instances for each send, but use a different action String for each; e.g., by appending an ID to a base action. As the Intents will then be inherently unequal, the PendingIntents will already be distinct, and the unique requestCode isn't necessary.

Upvotes: 1

Related Questions