3

I have an app that includes a service (WifiDirectFileTransferService) and a broadcast receiver (WifiDirectBroadcastReceiver). The broadcast receiver is used to receive global broadcasts (for WifiP2PManager.WIFI_P2P_..._ACTION). This part, receiving the global broadcasts, works fine.

Then I tried setting up the same broadcast receiver to also receive a local broadcast, for RECEIVED_MESSAGE_DONE_ACTION. Where I was already registering the receiver for global broadcasts in my activity, I added local registration:

@Override
protected void onResume() {
    super.onResume();
    // Register the broadcast receiver with the intent values to be matched.
    registerReceiver(mReceiver, mIntentFilter);
    // Register for local broadcasts too.
    Log.i(TAG, "onResume: registering local broadcast receiver " + mLocalIntentFilter.getAction(0));
    LocalBroadcastManager.getInstance(getApplicationContext())
          .registerReceiver(mReceiver, mLocalIntentFilter);
}

@Override
protected void onPause() {
    super.onPause();
    // Unregister the broadcast receiver.
    unregisterReceiver(mReceiver);
    Log.i(TAG, "onPause: unregistering local broadcast receiver " + mLocalIntentFilter.getAction(0));
    LocalBroadcastManager.getInstance(getApplicationContext())
          .unregisterReceiver(mReceiver);
}

The log messages confirm that the broadcast receiver is getting registered, and is not unregistered, before the broadcast occurs.

The local intent filter is initialized like this, in onCreate():

mLocalIntentFilter.addAction(WifiDirectBroadcastReceiver.RECEIVED_MESSAGE_DONE_ACTION);

The local broadcast is sent by the intent service during onHandleIntent():

Intent broadcastIntent = new Intent(RECEIVED_MESSAGE_DONE_ACTION)
     .putExtra(EXTRA_OTHER_DEVICE_ADDRESS, senderAddress.getHostAddress());

Log.i(TAG, "receiveMessage(): broadcasting " + broadcastIntent.toString());
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);

but the BroadcastReceiver's onReceive() never gets called for this broadcast. Why not?

Is it because the broadcast is being sent from a Service? That shouldn't matter... local broadcasts are supposed to work within the app, and the service is within the app. (And this comment confirms that a service can send a local broadcast to an activity within the same app.)

Is it because the same broadcast receiver is being used for both local and global broadcasts? That shouldn't matter either, as far as I can see. In fact, I tried an alternate version with a separate BroadcastReceiver for the local broadcast. The behavior remained the same: the local broadcast didn't appear to be received.

This question is not a duplicate of Local broadcast from Service not received by Activity, in which the problem was that the local broadcast receiver wasn't registered using LocalBroadcastManager.

Update: Just to be sure, I'm now using getApplicationContext() as the argument to LocalBroadcastManager.getInstance(), in case it matters whether you pass an activity context in one case and an application context in another. This didn't fix the problem.

Update 2

At David's request, I'm posting parts of the manifest.

<uses-permission android:name="android.permission.INTERNET" />

<!-- For Wi-Fi direct (https://developer.android.com/training/connect-devices-wirelessly/wifi-direct.html#create-group) -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Do we need this for WiFi Direct? -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

...

    <!-- The activity that registers the local broadcast. -->
    <activity android:name=".activity.ShareActivity"
              android:theme="@style/Theme.AppCompat.NoActionBar" />

    <!-- This is the service that sends the local broadcast. -->
    <service android:name=".comm.WifiDirectFileTransferService" />

If there are other parts you'd like to see, please let me know.

LarsH
  • 27,481
  • 8
  • 94
  • 152
  • 1
    post your manifest please – David Wasser Jul 13 '17 at 09:19
  • @DavidWasser, thanks for looking into this question. I can't post the whole manifest (company code), but I can post relevant parts. What part are you interested in? I'll post a few bits that seem related, but I can't think of anything that really should affect this question. – LarsH Jul 13 '17 at 14:01
  • Just for fun, please remove registering the `Receiver` with the `LocalBroadcastManager` and just add the appropriate `IntentFilter` to the set of `IntentFilter`s that you are listening for in the call to the register the global receiver. I'm not sure what's going on, just try this and see if it changes anything. – David Wasser Jul 13 '17 at 14:51
  • @DavidWasser: In the scenario you're talking about, you mean to keep broadcasting `RECEIVED_MESSAGE_DONE_ACTION` using `LocalBroadcastManager`, right? just don't use `LocalBroadcastManager` to register the receiver. OK I did that, and there's no change in behavior: The broadcast-sending code gets executed, but the broadcast-receiving code (`onReceive()`) doesn't. – LarsH Jul 13 '17 at 15:17
  • In your manifest, are you using `android:process="..."` anywhere? – David Wasser Jul 13 '17 at 16:12
  • Also, post the definition of `RECEIVED_MESSAGE_DONE_ACTION` in both `WifiDirectFileTransferService` and `WifiDirectBroadcastReceiver` – David Wasser Jul 13 '17 at 16:14
  • No, I don't use `android:process="..."` in the manifest. And there's only one definition of `RECEIVED_MESSAGE_DONE_ACTION`, which is imported. `public static final String RECEIVED_MESSAGE_DONE_ACTION = "received_message_done";` Good questions. – LarsH Jul 13 '17 at 19:06

1 Answers1

3

Found it! Talk about needle in a haystack :-)

You wrote:

Intent broadcastIntent = new Intent(RECEIVED_MESSAGE_DONE_ACTION)
 .putExtra(EXTRA_OTHER_DEVICE_ADDRESS, senderAddress.getHostAddress());

Log.i(TAG, "receiveMessage(): broadcasting " + broadcastIntent.toString());
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);

So you construct and log the broadcast Intent in variable broadcastIntent, but you call sendBroadcast() and pass the variable intent as an argument!

LarsH
  • 27,481
  • 8
  • 94
  • 152
David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • 1
    Wow, I believe you got it! Thank you!! You're right that was a needle in a haystack. The preexisting `intent` variable was the intent received by the service's `onHandleIntent()`. So of course it didn't have the right action. – LarsH Jul 13 '17 at 16:46
  • This is a good example of how descriptive variable names (or even types) can help prevent or find dumb mistakes. If I had named the `intent` variable `serviceIntent`, as I named the other one `broadcastIntent`, that might have made it easier to find the problem. – LarsH Jul 13 '17 at 19:01
  • 1
    BTW I will try to award a bounty if it lets me. – LarsH Jul 13 '17 at 19:07
  • 2
    2 years later, THANKYOU!!! This is the same, exact, dumb and insidious bug that was plaguing my afternoon. Thankyou!!! – Caterpillaraoz Sep 10 '19 at 14:03