BroadcastReceiver onReceive triggered when registe

2020-01-29 08:30发布

问题:

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

}

回答1:

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.



回答2:

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>


回答3:

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



回答4:

remove the following two lines they won't be triggered in onPause and onResume!

registerReceiver(connectivityReceiver, intentFilter);
unregisterReceiver(connectivityReceiver);