Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BroadcastReceiver onReceive triggered when registered

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());
    }

}
like image 434
Adam Brown Avatar asked May 07 '13 20:05

Adam Brown


People also ask

What is the role of the onReceive () method in the BroadcastReceiver?

Following are the two arguments of the onReceive() method: Context: This is used to access additional information, or to start services or activities. Intent: The Intent object is used to register the receiver.

What file is used to register the BroadcastReceiver?

You register this broadcast receiver either in the manifest file or in the code. These events are intents. So, whenever these kinds of events happen, an intent is triggered.

When would you use a BroadcastReceiver?

Broadcast in android is the system-wide events that can occur when the device starts, when a message is received on the device or when incoming calls are received, or when a device goes to airplane mode, etc. Broadcast Receivers are used to respond to these system-wide events.


3 Answers

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.

like image 163
David Wasser Avatar answered Sep 28 '22 06:09

David Wasser


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>
like image 38
Adam Brown Avatar answered Sep 28 '22 06:09

Adam Brown


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

like image 39
y.allam Avatar answered Sep 28 '22 04:09

y.allam