I have a broadcast receiver which is being triggered the moment it's registered (and subsequently retriggered with onPause / onResume), surely this is the wrong behaviour? Have I missed something here?
class FooActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
broadcastReceiver = new FooBroadcastReceiver();
intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(connectivityReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(connectivityReceiver);
}
class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (connectivityAction(intent)) {
Log.d("footag", "onReceive");
}
}
private boolean connectivityAction(Intent intent) {
return ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction());
}
}
The CONNECTIVITY_ACTION
broadcast seems to be sticky on some devices (even though the documentation implies that it is not). This means that when you register the receiver it will immediately call onReceive()
with the most recently sent broadcast. Since you are registering and unregistering in onPause()
and onResume()
you will get a lot of calls to onReceive()
. You might want to do this in a different way.
Thanks for the answers! My solution was a result of them all, by switching to a manifest declared receiver and enabling/disabling the receiver component in onResume/onPause stopped the sticky nature of the receiver. And by enabling/disabling the component I can have piece of mind that I'm a second class citizen.
@Override
protected void onResume() {
super.onResume();
setReceiverState(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
}
@Override
protected void onPause() {
super.onPause();
setReceiverState(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
}
private void setReceiverState(int receiverState) {
ComponentName receiver = new ComponentName(this, FooBroadcastReceiver.class);
PackageManager pm = this.getPackageManager();
pm.setComponentEnabledSetting(receiver, receiverState,
PackageManager.DONT_KILL_APP);
}
AndroidManifest.xml
<receiver android:name="com.example.receiver.FooBroadcastReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
Here's another solution that worked for me:
class FooActivity extends Activity {
private Intent mReceiverRegisteringIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
broadcastReceiver = new FooBroadcastReceiver();
intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
}
@Override
protected void onResume() {
super.onResume();
mReceiverRegisteringIntent = registerReceiver(connectivityReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(connectivityReceiver);
}
private class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (connectivityAction(intent)) {
Log.d("footag", "onReceive");
//if mReceiverRegisteringIntent is not null, then this is the sticky
//broadcast received when registering the receiver for the first time
if (mReceiverRegisteringIntent != null) {
//set it to null for future broadcasts
mReceiverRegisteringIntent = null;
return; //do nothing
}
//logic for future broadcasts
...
}
}
private boolean connectivityAction(Intent intent) {
return ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction());
}
}
}
I'm assuming that MyBroadcastReceiver
is an inner class for FooActivity
so it can access mReceiverRegisteringIntent
remove the following two lines they won't be triggered in onPause and onResume!
registerReceiver(connectivityReceiver, intentFilter);
unregisterReceiver(connectivityReceiver);