Why isn't my local broadcast from a service be

2019-07-04 07:13发布

问题:

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.

回答1:

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!