Search code examples
androidbroadcastreceiver

Can't get embedded BroadcastReceiver to work


This is for a GPS. I have a parent class with an embedded receiver class, and a separate LocationTrackingService class that handles the GPS stuff. I need to Broadcast the mileage traveled to update the UI, but the broadcast is never received. This is the only BroadcastReceiver in the project. I guess I could set a timer to have my ServiceConnection check every couple of seconds and grab the new mileage, but that's bad coding.

Nothing is in the Manifest because I'm registering and unregistering dynamically.

public class Parent
{
  GPSReceiver gpsreceiver;

  public class EmbeddedReceiver extends BroadcastReceiver
  {
    @Override
    public void onReceive(Context arg0, Intent intent)
    {
      Bundle extras = intent.getExtras();
      if (extras != null) {
        distance = extras.getDouble(LocationTrackingService.UPDATE_MILEAGE_MESSAGE);
      }
    }
  }

  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    gpsReceiver = new EmbeddedReceiver();
  }

  private void gpsStart()
  {
    if (gpsReceiver != null) {
      intentFilter = new IntentFilter();
      intentFilter.addAction("don't know what goes here");
      LocalBroadcastManager.getInstance(this).registerReceiver(gpsReceiver, intentFilter);
    }
  }

  private void gpsStop()
  {
    if (gpsReceiver != null) {
      LocalBroadcastManager.getInstance(this).unregisterReceiver(gpsReceiver);
    }
  }
}

public class LocationTrackingService extends Service
{
  private LocalBroadcastManager broadcaster;

  @Override
  public int onStartCommand(Intent intent, int flags, int startId)
  {
    super.onStartCommand(intent, flags, startId);

    broadcaster = LocalBroadcastManager.getInstance(this);
    return START_STICKY;
  }

  .... code

  private void sendResult(String message)
  {
    Intent i = new Intent("ParentActivity");
    i.setAction("ParentActivity");
    if (message != null) {
      i.putExtra(message, mileageRunningTotal);
    }

    broadcaster.sendBroadcast(i);
  }
}

When I follow the code into LocalBroadcastManager, on line 215 it does mActions.get(intent.getAction() to get an ArrayList<ReceiverRecord>, and it's null, but I don't know why.

I appreciate any help you can give.


Solution

  • Broadcasts work in such a way that the action acts as a trigger for the receiver. In other words, there are tons of broadcasts being sent around throughout your phone at any given time, the goal of the receiver is to catch the broadcast with the corresponding action when it flies by. It will let all other broadcasts continue through without interruption. Once it finds the one it is looking for, it will receive it and perform the onReceive() functionality.

    Though an action can be any string key you care for it to be, it is advised to add in your package name. This gives specificity to your broadcast and allows your broadcast to be more easily managed in the barrage of broadcasts that your phone is sending. This is important as broadcasts can be sent between applications. It makes it so you avoid the following scenario

    Application A sends out a system broadcast with action "SOME_ACTION" which we have no interest in. Application B will also be sending out a local broadcast with action "SOME_ACTION" which we are awnt to receive. We will setup Receiver 1 to look for and receive the action "SOME_ACTION" from Application B. However, because of conflicting actions, when Application A sends out a broadcast of "SOME_ACTION", we will inappropriately receive it in Receiver 1 and perform our onReceive() functionality as though we had just received a local broadcast from Application B.

    Following recommended convention, you avoid the above situation by doing the following

    Instead of setting your action as "SOME_ACTION", it would be set to "com.app_b.package.SOME_ACTION". That way when the broadcast action "com.app_a.package.SOME_ACTION" passes by, it won't be confused for our action and will be allowed to pass.

    There may be other reasons for using package name, and this may not be the best of them, but to the best of my knowledge this is the reasoning behind the convention.