Broadcast receiver for checking internet connection in android app

后端 未结 21 3185
温柔的废话
温柔的废话 2020-11-21 22:28

I am developing an android broadcast receiver for checking internet connection.

The problem is that my broadcast receiver is being called two times. I want it to get

相关标签:
21条回答
  • 2020-11-21 22:47

    manifest:

    <receiver android:name=".your.namepackage.here.ConnectivityReceiver">
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
        </intent-filter>
    </receiver>
    

    class for receiver:

    public class ConnectivityReceiver extends BroadcastReceiver{
    
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            switch (action) {
                case ConnectivityManager.CONNECTIVITY_ACTION:
                    DebugUtils.logDebug("BROADCAST", "network change");
                    if(NetworkUtils.isConnect()){
                        //do action here
                    }
                break;
            }
        }
    }
    

    and classs utils like example:

    public class NetworkUtils {
    
        public static boolean isConnect() {
            ConnectivityManager connectivityManager = (ConnectivityManager) Application.getInstance().getSystemService(Context.CONNECTIVITY_SERVICE);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                Network[] netArray = connectivityManager.getAllNetworks();
                NetworkInfo netInfo;
                for (Network net : netArray) {
                    netInfo = connectivityManager.getNetworkInfo(net);
                    if ((netInfo.getTypeName().equalsIgnoreCase("WIFI") || netInfo.getTypeName().equalsIgnoreCase("MOBILE")) && netInfo.isConnected() && netInfo.isAvailable()) {
                        //if (netInfo.getState().equals(NetworkInfo.State.CONNECTED)) {
                        Log.d("Network", "NETWORKNAME: " + netInfo.getTypeName());
                        return true;
                    }
                }
            } else {
                if (connectivityManager != null) {
                    @SuppressWarnings("deprecation")
                    NetworkInfo[] netInfoArray = connectivityManager.getAllNetworkInfo();
                    if (netInfoArray != null) {
                        for (NetworkInfo netInfo : netInfoArray) {
                            if ((netInfo.getTypeName().equalsIgnoreCase("WIFI") || netInfo.getTypeName().equalsIgnoreCase("MOBILE")) && netInfo.isConnected() && netInfo.isAvailable()) {
                                //if (netInfo.getState() == NetworkInfo.State.CONNECTED) {
                                Log.d("Network", "NETWORKNAME: " + netInfo.getTypeName());
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }
    }
    
    0 讨论(0)
  • 2020-11-21 22:47

    Add a broadcast receiver which can listen to network connectivity change. Then check wether device is connected to internet or not using ConnectivityManager. Refer to this post or video for detailed understanding. Below is the code:

    public class NetworkStateChangeReceiver extends BroadcastReceiver {
      public static final String NETWORK_AVAILABLE_ACTION = "com.ajit.singh.NetworkAvailable";
      public static final String IS_NETWORK_AVAILABLE = "isNetworkAvailable";
    
      @Override
      public void onReceive(Context context, Intent intent) {
        Intent networkStateIntent = new Intent(NETWORK_AVAILABLE_ACTION);
        networkStateIntent.putExtra(IS_NETWORK_AVAILABLE,  isConnectedToInternet(context));
        LocalBroadcastManager.getInstance(context).sendBroadcast(networkStateIntent);
      }
    
      private boolean isConnectedToInternet(Context context) {
        try {
          if (context != null) {
            ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
            return networkInfo != null && networkInfo.isConnected();
          }
          return false;
        } catch (Exception e) {
          Log.e(NetworkStateChangeReceiver.class.getName(), e.getMessage());
          return false;
        }
      }
    }
    

    I wrote this receiver to show a notification on the Screen, that's why you see a local broadcast with the network status. Here is the code to show the notification.

    public class MainActivity extends AppCompatActivity {
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        IntentFilter intentFilter = new IntentFilter(NetworkStateChangeReceiver.NETWORK_AVAILABLE_ACTION);
        LocalBroadcastManager.getInstance(this).registerReceiver(new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
            boolean isNetworkAvailable = intent.getBooleanExtra(IS_NETWORK_AVAILABLE, false);
            String networkStatus = isNetworkAvailable ? "connected" : "disconnected";
    
            Snackbar.make(findViewById(R.id.activity_main), "Network Status: " + networkStatus, Snackbar.LENGTH_LONG).show();
          }
        }, intentFilter);
      }
    }
    

    Activity listens to the intent broadcasted by the network receiver and shows the notification on the screen.

    0 讨论(0)
  • 2020-11-21 22:48

    I know this thread is old and fully answered but I feel that the following might help some people.

    The code in the body of the question contains a bug which no one here addressed. @Nikhil is checking whether the wifi/mobile is available and not if it's connected.

    The fix is here:

    @Override
    public void onReceive(final Context context, final Intent intent) {
        final ConnectivityManager connMgr = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
    
        final android.net.NetworkInfo wifi = connMgr
                .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    
        final android.net.NetworkInfo mobile = connMgr
                .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    
        if (wifi.isConnected() || mobile.isConnected()) {
          // do stuff
        }
    }
    
    0 讨论(0)
  • 2020-11-21 22:48

    Warning: Declaring a broadcastreceiver for android.net.conn.CONNECTIVITY_CHANGE is deprecated for apps targeting N and higher. In general, apps should not rely on this broadcast and instead use JobScheduler or GCMNetworkManager.

    As CONNECTIVITY_CHANGE is deprecated then we should use another way of doing the same stuff

    Following NetworkConnectionLiveData will handle all the OS Version till now and also if target SDK is less than Build.VERSION_CODES.LOLLIPOP then only we can use broadcastReceiver

    Best Part is this class uses LiveData so no need to register any receiver use LiveData and it will handle all the things

    class NetworkConnectionLiveData(val context: Context) : LiveData<Boolean>() {
    
        private var connectivityManager: ConnectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
    
        private lateinit var connectivityManagerCallback: ConnectivityManager.NetworkCallback
    
        override fun onActive() {
            super.onActive()
            updateConnection()
            when {
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> connectivityManager.registerDefaultNetworkCallback(getConnectivityManagerCallback())
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> lollipopNetworkAvailableRequest()
                else -> {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                        context.registerReceiver(networkReceiver, IntentFilter("android.net.conn.CONNECTIVITY_CHANGE"))
                    }
                }
            }
        }
    
        override fun onInactive() {
            super.onInactive()
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                connectivityManager.unregisterNetworkCallback(connectivityManagerCallback)
            } else {
                context.unregisterReceiver(networkReceiver)
            }
        }
    
        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        private fun lollipopNetworkAvailableRequest() {
            val builder = NetworkRequest.Builder()
                    .addTransportType(android.net.NetworkCapabilities.TRANSPORT_CELLULAR)
                    .addTransportType(android.net.NetworkCapabilities.TRANSPORT_WIFI)
            connectivityManager.registerNetworkCallback(builder.build(), getConnectivityManagerCallback())
        }
    
        private fun getConnectivityManagerCallback(): ConnectivityManager.NetworkCallback {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    
                connectivityManagerCallback = object : ConnectivityManager.NetworkCallback() {
                    override fun onAvailable(network: Network?) {
                        postValue(true)
                    }
    
                    override fun onLost(network: Network?) {
                        postValue(false)
                    }
                }
                return connectivityManagerCallback
            } else {
                throw IllegalAccessError("Should not happened")
            }
        }
    
        private val networkReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                updateConnection()
            }
        }
    
        private fun updateConnection() {
            val activeNetwork: NetworkInfo? = connectivityManager.activeNetworkInfo
            postValue(activeNetwork?.isConnected == true)
        }
    } 
    

    Use of the LiveData into any class:

    NetworkConnectionLiveData(context ?: return)
        .observe(viewLifecycleOwner, Observer { isConnected ->
            if (!isConnected) {
                // Internet Not Available
                return@Observer
            }
            // Internet Available
    })
    
    0 讨论(0)
  • 2020-11-21 22:48

    Add permissions:

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
    

    Create Receiver to check for connection

    public class NetworkChangeReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(final Context context, final Intent intent) {
    
            if(checkInternet(context))
            {
                Toast.makeText(context, "Network Available Do operations",Toast.LENGTH_LONG).show(); 
            }
    
        }
    
        boolean checkInternet(Context context) {
            ServiceManager serviceManager = new ServiceManager(context);
            if (serviceManager.isNetworkAvailable()) {
                return true;
            } else {
                return false;
            }
        }
    
    }
    

    ServiceManager.java

    public class ServiceManager {
    
        Context context;
    
        public ServiceManager(Context base) {
            context = base;
        }
    
        public boolean isNetworkAvailable() {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = cm.getActiveNetworkInfo();
            return networkInfo != null && networkInfo.isConnected();
        }
    }
    
    0 讨论(0)
  • 2020-11-21 22:49

    It's easier to use https://github.com/JobGetabu/DroidNet

     @Override
        public void onInternetConnectivityChanged(boolean isConnected) {
    
            if (isConnected) {
                //do Stuff with internet
                netIsOn();
            } else {
                //no internet
                netIsOff();
            }
        }
    
        private void netIsOn(){...}
    
        private void netIsOff(){...}
    
    0 讨论(0)
提交回复
热议问题