BroadcastReceiver receives multiple identical messages for one event

后端 未结 6 1373
伪装坚强ぢ
伪装坚强ぢ 2020-12-02 11:10

I registered a receiver that listens to network events:



        
相关标签:
6条回答
  • 2020-12-02 11:56

    You can also cache in a static field the last handled connection type and check against the incomming broadcasts. This way you will only get one broadcast per connection type.

    When connection type gets changed it will obviously work. When device gets out of connection activeNetworkInfo will be null and currentType will be NO_CONNECTION_TYPE as in default case.

    public class ConnectivityReceiver extends BroadcastReceiver {
    
        /** The absence of a connection type. */
        private static final int NO_CONNECTION_TYPE = -1;
    
        /** The last processed network type. */
        private static int sLastType = NO_CONNECTION_TYPE;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            ConnectivityManager connectivityManager = (ConnectivityManager)
                    context.getSystemService(Context.CONNECTIVITY_SERVICE);
    
            NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
            final int currentType = activeNetworkInfo != null
                    ? activeNetworkInfo.getType() : NO_CONNECTION_TYPE;
    
            // Avoid handling multiple broadcasts for the same connection type
            if (sLastType != currentType) {
                if (activeNetworkInfo != null) {
                    boolean isConnectedOrConnecting = activeNetworkInfo.isConnectedOrConnecting();
                    boolean isWiFi = ConnectivityManager.TYPE_WIFI == currentType;
                    boolean isMobile = ConnectivityManager.TYPE_MOBILE == currentType;
    
                    // TODO Connected. Do your stuff!
                } else {
                    // TODO Disconnected. Do your stuff!
                }
    
                sLastType = currentType;
            }
    }
    
    0 讨论(0)
  • 2020-12-02 11:57

    Register your LocalBroadcastreceiver in oncreate() itself not in onResume(). unregistered in onDestroy

    0 讨论(0)
  • 2020-12-02 12:06

    My concern with the approach proposed by Aleksander is that it doesn't consider network changes of the same type, e.g. from one WiFi network to another.

    I'm proposing to compare the extraInfo of the active network, which contains the network name, e.g. WiFi SSID or mobile network name like VZW

     String currentNetworkName = "";
    
     ConnectivityManager connectivityManager =
                ((ConnectivityManager) context.getSystemService(
                        Context.CONNECTIVITY_SERVICE));
    
        NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
        boolean connected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
        if (connected) {
            // prevent duplicate connect broadcasts
            String extraInfo = activeNetwork.getExtraInfo();
            if(! currentNetworkName.equals(extraInfo)) {
                // to do: handle network changes
                currentNetworkName = extraInfo;
            }
        } else {
            Log.d(TAG, "is not connected");
            isConnected = false;
            currentNetworkName = "";
        }
    
    0 讨论(0)
  • 2020-12-02 12:07

    I have an application that uploads data when the user comes back online. Since my broadcast receiver can receive the intent multiple times, it can lead to the data being uploaded more than once. To handle this, I use a service that will not do anything if it is already running.

    Broadcast Receiver:

    public class ConnectionChangeReceiver extends BroadcastReceiver {
        private static boolean firstConnect = true;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            final NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
            if (activeNetInfo != null) {
                startService();
            }   
        }
    }
    

    Service:

    public class MyService extends Service {
        private boolean mRunning;
    
        @Override
        public void onCreate() {
            super.onCreate();
            mRunning = false;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            if (!mRunning) {
                mRunning = true;
                uploadTheData();
            }
            return super.onStartCommand(intent, flags, startId);
        }
    }
    
    0 讨论(0)
  • 2020-12-02 12:08

    Receiving multiple broadcast is a device specific problem. Some phones just send one broadcast while other send 2 or 3. But there is a work around:

    Assuming you get the disconnect message when the wifi is disconnected, I would guess the first one is the correct one and the other 2 are just echoes for some reason.

    To know that the message has been called, you could have a static boolean that gets toggled between connect and disconnect and only call your sub-routines when you receive a connection and the boolean is true. Something like:

    public class ConnectionChangeReceiver extends BroadcastReceiver {
        private static boolean firstConnect = true;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            final NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
            if (activeNetInfo != null) {
                if(firstConnect) { 
                    // do subroutines here
                    firstConnect = false;
                }
            }
            else {
                firstConnect= true;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 12:11

    In my case, I was registering my BroadcastReceivers in onResume and only unregistering them in onDestroy.

    This caused each broadcastreceiver to be registered 3 or 4 times depending on how many times the activity resumes.

    Setting your broadcastreceiver in the right place in terms of the activity lifecycle will allow you to stop getting multiple confusing calls.

    0 讨论(0)
提交回复
热议问题