Search code examples
androidbroadcastreceiver

why onReceive() is being called many times?


i do not know why when i connect or disconnect the wifi, the corresponding callback in the below posted code of the wifi receiver, is called many times at least three times, and

therefore, if i want to call a function based on the current wifi state, that function will be called many times and i do not want such behaviour, especially that, in the

function that should be called when there is wifi connection, i am displaying a dialog, and being that callback will be called many times, the dialog will be called many times and it will cause overlap.

please have alok at the below posted logcat, it is just an example o what i am getting.

please let me know why the corresponding callback of the wifi status is getting called many times, and how to avoid such multiple calling?

code:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    tv_status = (TextView) findViewById(R.id.tv_status);

    this.registerReceiver(this.myWifiReceiver, new IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));
}

private BroadcastReceiver myWifiReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        Log.d(TAG, "@onReceive()");

        mConnMgr = (ConnectivityManager)getSystemService(network_service);
        WifiManager wifiMgr = (WifiManager) context.getSystemService(WiFi_Service);

        switch (wifiMgr.getWifiState()) {
        case WifiManager.WIFI_STATE_ENABLED:
            Log.d(TAG, "wifi enabled");

            if (mConnMgr != null) {
                networkInfo = mConnMgr.getActiveNetworkInfo();
                if (networkInfo != null) {
                    switch(networkInfo.getType()) {
                    case ConnectivityManager.TYPE_WIFI: 
                        if (networkInfo.isConnected()) {
                            tv_status.setText("Connected");
                            Log.d(TAG, "Connected");
                        }else if (networkInfo.isConnectedOrConnecting()) {
                            tv_status.setText("Status: CONNECTED Or CONNECTING");
                            Log.d(TAG, "Status: CONNECTED Or CONNECTING");
                        }else if (networkInfo.isFailover()){
                            Log.d(TAG, "Status: FailOver");
                        }else if (networkInfo.isRoaming()) {
                            Log.d(TAG, "Status: Roaming");
                        }else if (networkInfo.isAvailable()) {
                            Log.d(TAG, "Status: Available");
                        } else {
                            Log.d(TAG, "Status: disconnected");
                        }
                        break;

                    }
                }else {
                    tv_status.setText("Status: No Default NetWork Connected");
                    Log.d(TAG, "Status: No Default NetWork Connected");
                }
            } else {
                tv_status.setText("Status:  ConnMgr is null");
                Log.d(TAG, "Status:  ConnMgr is null");
            }

            break;

LogCat:

03-04 15:31:31.031: D/MainActivity(16120): @onReceive()
03-04 15:31:31.031: D/MainActivity(16120): wifi enabled
03-04 15:31:31.032: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:31:31.546: D/MainActivity(16120): @onReceive()
03-04 15:31:31.547: D/MainActivity(16120): wifi enabled
03-04 15:31:31.547: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:31:31.617: D/MainActivity(16120): @onReceive()
03-04 15:31:31.618: D/MainActivity(16120): wifi enabled
03-04 15:31:31.620: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:31:31.636: D/MainActivity(16120): @onReceive()
03-04 15:31:31.636: D/MainActivity(16120): wifi enabled
03-04 15:31:31.637: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:32:28.661: D/MainActivity(16120): @onReceive()
03-04 15:32:28.663: D/MainActivity(16120): wifi enabled
03-04 15:32:28.666: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:32:28.708: D/MainActivity(16120): @onReceive()
03-04 15:32:28.709: D/MainActivity(16120): wifi enabled
03-04 15:32:28.710: D/MainActivity(16120): Status: No Default NetWork Connected
03-04 15:32:28.722: D/MainActivity(16120): @onReceive()
03-04 15:32:28.722: D/MainActivity(16120): wifi enabled
03-04 15:32:28.722: D/MainActivity(16120): Status: No Default NetWork Connected

Update_1:

MySolution using a Timer:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_activity);

    tv_status = (TextView) findViewById(R.id.tv_status);
    IntentFilter intfil = new IntentFilter(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);

    this.registerReceiver(this.myWifiReceiver, intfil);
}

private BroadcastReceiver myWifiReceiver = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        Log.d(TAG, "@onReceive()");
        Timer t1 = new Timer();
        Timer t2 = new Timer();

        if (!locked) {
            if (scheduled1) {
                t1.cancel();
                t1.purge();
            }
            if (scheduled2) {
                t2.cancel();
                t2.purge();
            }

            WifiManager wifiMgr = (WifiManager) context.getSystemService(WiFi_Service);

            switch (wifiMgr.getWifiState()) {
            case WifiManager.WIFI_STATE_ENABLED:
                Log.d(TAG, "wifi enabled");
                locked = true;
                t1 = new Timer();
                t1.schedule(MQTTReceiverLockTimedTask, 4000);
                scheduled1 = true;
                module();
                break;

            case WifiManager.WIFI_STATE_DISABLED:
                Log.d(TAG, "wifi disabled");
                locked = true;
                t2 = new Timer();
                t2.schedule(MQTTReceiverLockTimedTask, 4000);
                scheduled2 = true;
                break;
            }
        }
    }
};

TimerTask MQTTReceiverLockTimedTask = new TimerTask() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        locked = false;
    }
};

protected void module() {
    // TODO Auto-generated method stub
    mConnMgr = (ConnectivityManager)getSystemService(network_service);

    if (mConnMgr != null) {
        networkInfo = mConnMgr.getActiveNetworkInfo();
        if (networkInfo != null) {
            switch(networkInfo.getType()) {
            case ConnectivityManager.TYPE_WIFI: 
                if (networkInfo.isConnected()) {
                    tv_status.setText("Connected");
                    Log.d(TAG, "Connected");
                }else if (networkInfo.isConnectedOrConnecting()) {
                    tv_status.setText("Status: CONNECTED Or CONNECTING");
                    Log.d(TAG, "Status: CONNECTED Or CONNECTING");
                }else if (networkInfo.isFailover()){
                    Log.d(TAG, "Status: FailOver");
                }else if (networkInfo.isRoaming()) {
                    Log.d(TAG, "Status: Roaming");
                }else if (networkInfo.isAvailable()) {
                    Log.d(TAG, "Status: Available");
                } else {
                    Log.d(TAG, "Status: disconnected");
                }
                break;

            }
        }else {
            tv_status.setText("Status: No Default NetWork Connected");
            Log.d(TAG, "Status: No Default NetWork Connected");
        }
    } else {
        tv_status.setText("Status:  ConnMgr is null");
        Log.d(TAG, "Status:  ConnMgr is null");
    }
}

Solution

  • From the WifiManager documentation on WifiManager.SUPPLICANT_STATE_CHANGED_ACTION:

    Broadcast intent action indicating that the state of establishing a connection to an access point has changed.One extra provides the new SupplicantState.

    You are getting many calls to onReceive()because SupplicantState provides a more detailed information on the state of the establishing connection. Every time this state changes, a new intent is broadcast. Since you only need a less detailed information from this, it seems that you are getting same broadcasts many times.

    As on how to avoid this: either search for another intent to listen, such as ConnectivityManager.CONNECTIVITY_ACTION if it suits your needs, or try Mahmoud Elmorabea's solution - save the current wifi connection state in a private field on your Activity class, and on the onReceive(), check if the connection state has changed. If it has not, skip the rest of the code. Otherwise, run the code and update your status. If you use this solution, remember to save the state field during the Activity lifecycle.