17

I am using a local broadcast to let my service know that the AsyncTask has finished its work but I have a small issue : the broadcast is only sent once (it is created by a function that is only called when the app is launched) but I receive it twice.

simplified code :

@Override
protected void onPostExecute(HttpResponse result) {
    LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(getBaseContext());
    localBroadcastManager.sendBroadcast(new Intent(getString(R.string.bc_CONNECTED)));
}

in the service:

private BroadcastReceiver connectedBroadcastReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d(getString(R.string.app_tag), "broadcast received !!");
    }
};

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    LocalBroadcastManager.getInstance(this).registerReceiver(connectedBroadcastReceiver, new IntentFilter(getString(R.string.bc_CONNECTED)));
    return START_STICKY;
}

Has anyone encountered such a weird behavior yet?

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
Teovald
  • 4,369
  • 4
  • 26
  • 45

5 Answers5

27

I had the same issue, the problem was that I was registrering the receiver in the onCreate method and in the onResume method. Removing from the onCreate the problem was solved.

Oriol
  • 271
  • 1
  • 3
  • 3
  • 1
    Thanks, this was my issue. – Robby Smet Jul 18 '13 at 10:02
  • Does this also apply to BroadcastReceiver? With the new SDK release (26) now we have to manually register the receivers. I was wondering if it is safe to call the registerReceiver method twice?. Because of the way my application works, I need to make sure that the receiver is registered in different circumstances, but, since no "isReceiverRegistered" method exists, the only way to do this is by simply registering the receiver but I'm afraid I might be registering it twice and getting the messages twice. – Roger May 21 '18 at 23:17
12

You should always check for the intent Action before responding to the broadcast.

public void onReceive(Context context, Intent intent){
      if(intent.getAction() != null && intent.getAction().equals(getString(R.string.bc_CONNECTED))){
      Log.d(getString(R.string.app_tag), "broadcast received !!");
 }
}

Check the documentation. It says you may receive spurious calls. So always check for action

The Intent filters used in registerReceiver(BroadcastReceiver, IntentFilter) and in application manifests are not guaranteed to be exclusive. They are hints to the operating system about how to find suitable recipients. It is possible for senders to force delivery to specific recipients, bypassing filter resolution. For this reason, onReceive() implementations should respond only to known actions, ignoring any unexpected Intents that they may receive.

nandeesh
  • 24,740
  • 6
  • 69
  • 79
  • Arg, I thought that my IntentFilter would ward me against spurious calls since it contains my package name but it may be the case. I will reproduce the issue in order to validate its source. Thanks ! – Teovald Sep 24 '12 at 11:07
  • @nandeesh what the difference between if(intent.getAction() != null && intent.getAction().equals(getString(R.string.bc_CONNECTED))) and if(intent.getAction().equals(getString(R.string.bc_CONNECTED)))? – Sazzad Hissain Khan Jul 03 '14 at 13:47
  • @Hissain just some NPE protection. – Teovald Nov 10 '14 at 12:25
  • what is value of `R.string.bc_CONNECTED`? – hasnain_ahmad Jun 12 '17 at 07:07
1

I had this issue because I was registering twice as I had two intent Filters. So system was passing the same intent twice.

  LocalBroadcastManager.getInstance(this).registerReceiver(mLocalReceiver,intentFilterNews);
  LocalBroadcastManager.getInstance(this).registerReceiver(mLocalReceiver,intentFilterWeather);
Harish Rana
  • 484
  • 3
  • 8
1

Do you unregister the receiver when exiting the app? Otherwise you get with each app start another receiver registered. Or you must check, whether the receiver has already been registered on a previous app call, before you register it.

sfive
  • 11
  • 2
1

Make sure to register BroadcastReceiver in onCreate method of any component (Activity, Fragment, Service etc...) instead of onResume or onViewCreated (in case of fragmnet)

e.g.

val receiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        Log.d("TAGGg",intent?.getBooleanExtra("ext", false).toString())
    }
}

// On Create method of component
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    LocalBroadcastManager.getInstance(requireActivity()).registerReceiver(receiver, IntentFilter("test-event"))
}

Also make sure to unregister receiver in onStop() or onDestroy()

LocalBroadcastManager.getInstance(requireActivity()).unregisterReceiver(receiver)
Amir Raza
  • 2,320
  • 1
  • 23
  • 32