Search code examples
androidbroadcastreceiverandroid-broadcast

Sticky Broadcast Receivers - how do they work?


Are Broadcast Receivers sticky or Intents sticky? From what I know- "sticky intents are those which stick around after they are broadcast. There is no such thing as sticky Broadcast Receivers; there are only receivers who can listen to sticky intents."

But how do we make intents sticky? Is sendStickyBroadcast(intentA) is the only way to make intentA sticky? If yes, what would happen if I call both sendStickyBroadcast(intentA) and sendBroadcast(intentA) ? Will the intentA be available for future receivers?

I wanted to test this scenario with Logcat, but I have been receiving unexpected logs:

public class MainActivity extends Activity {

    private static final String CUSTOM_INTENT = "com.ashok.abacussb.my_intent";
    Button button;
    Receiver1 receiver1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        sendBroadcast(new Intent(CUSTOM_INTENT));
        Log.d("abd", "after sendBroadcast() "+ Thread.currentThread().getName());

        receiver1 = new Receiver1();

        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("abd", "inside onClick()");
                Intent intent = registerReceiver(receiver1, new IntentFilter(CUSTOM_INTENT));
                Log.d("abd", (intent == null ? "null": ""+intent));
            }
        });
    }
}

public class Receiver1 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("abd", "inside Receiver1 onReceive() "+ Thread.currentThread().getName());
    }
}

and the LOGS:

09-21 16:26:43.845: D/abd(26620): after sendBroadcast() main
09-21 16:26:49.665: D/abd(26620): inside onClick()
09-21 16:26:49.685: D/abd(26620): Intent { act=com.ashok.abacussb.my_intent flg=0x10 }
09-21 16:26:49.770: D/abd(26620): inside Receiver1 onReceive() main

Receiver1 is registered on button click, which is clearly after sendBroadcast() is executed. Why is the onReceive() method executed & the intent returned by registerReceiver() not NULL, since it was not a sendStickyBroadcast() ?


Solution

  • Are Broadcast Receivers sticky or Intents sticky?

    Broadcast Intents sent via sendStickyBroadcast() are sticky, if you hold the proper permission to send such broadcasts.

    Is sendStickyBroadcast(intentA) is the only way to make intentA sticky?

    Yes.

    If yes, what would happen if I call both sendStickyBroadcast(intentA) and sendBroadcast(intentA) ? Will the intentA be available for future receivers?

    AFAIK, the behavior is undocumented. I would not recommend using that pattern.

    Why is the onReceive() method executed & the intent returned by registerReceiver() not NULL, since it was not a sendStickyBroadcast() ?

    Perhaps you previously sent a sticky broadcast for that same action string. Reboot your device or emulator and try your test again.