2

I am developing an SMS app and want to check for network (cellular) connection. With API level 29, checking for connection requires use of ConnectivityManager.NetworkCallback. What I have managed is to get 'onAvailable()` to inform me when a network becomes available. However, that will also inform me if it connects to WiFi (so I could have no service to send an SMS but if WiFI connects then onAvailable() will fire).

I tried onCapabilitiesChanged() and .hasTransport(TRANSPORT_CELLULAR) but that reports false if I am connected to WiFi.

I also thought to try hasCapability(NET_CAPABILITY_MMS) but that informs if MMS is possible. It's not clear to me if there is a scenario/network where SMS is possible but MMS is not? So could I get this reporting false because network does not support MMS but can still send SMS?

What is the correct method for checking if cellular network is available?

SimpleOne
  • 1,066
  • 3
  • 12
  • 29

4 Answers4

3

Maybe you can try the following

Network activeNetwork = connectivityManager.getActiveNetwork();
NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(activeNetwork);
boolean cellular = caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);

if(cellular){
   // do your stuff
}

Mithun Sarker Shuvro
  • 3,902
  • 6
  • 32
  • 64
  • Thanks but according to the [docs](https://developer.android.com/reference/android/net/ConnectivityManager.html#getActiveNetwork()), that was deprecated in API level 29. – SimpleOne Jul 24 '19 at 12:02
  • And, essentially, I have tried the same thing using the latest API but get a `FALSE` when connected to WiFI – SimpleOne Jul 24 '19 at 12:27
  • so, it means that you should combine transport checks (`NetworkCapabilities.TRANSPORT_WIFI`). TRANSPORT_CELLULAR checks only mobile internet connection. – Alexander Dadukin Oct 29 '19 at 06:27
1

Late to the pary, and I'm not sure about 29... and I guess it is quite lame... but this is how I did it:

public boolean isCellularAvailable()
{
    TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    String opetarorName = telephonyManager.getNetworkOperatorName();

    Log.i(LOG_TAG, "#### isCellularAvailable(): NetworkOperatorName is: " + opetarorName );

    if (opetarorName .compareTo("") == 0)
    {
        Log.i(LOG_TAG, "#### isCellularAvailable(): NOPE");
        Toast.makeText(context, "Turn off airplane mode and try again :)", Toast.LENGTH_LONG).show();
        return false;
    }
    else
    {
        Log.i(LOG_TAG, "#### isCellularAvailable(): YES!");
        return true;
    }
}

The idea here is that if you are connected to a cellular network you should be able to get the name of your network provider.

If you get the name of one, then you are connected to that network, and should will be able to use it.

If you are in e.g. airplane mode, you will not be connected to a network, and will not get a name.

Noted that documentation says “Result may be unreliable on CDMA networks”… whatever that means.

But the “telephonyManager” offers a few similar functions, e.g. “getNetworkType()” might be another way to go if you know you´re favorable network types:

public boolean isCellularAvailable()
{
    TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    int networkType = telephonyManager.getNetworkType();// .getNetworkOperatorName();

    Log.i(LOG_TAG, "#### isCellularAvailable(): Network type is: " + networkType);

    switch (networkType)
    {
        // Return true for networks that suits your purpose
        case TelephonyManager.NETWORK_TYPE_1xRTT:    return true;
        case TelephonyManager.NETWORK_TYPE_CDMA:     return true;
        case TelephonyManager.NETWORK_TYPE_EDGE:     return true;
        case TelephonyManager.NETWORK_TYPE_EHRPD:    return true;
        case TelephonyManager.NETWORK_TYPE_EVDO_0:   return true;
        case TelephonyManager.NETWORK_TYPE_EVDO_A:   return true;
        case TelephonyManager.NETWORK_TYPE_EVDO_B:   return true;
        case TelephonyManager.NETWORK_TYPE_GPRS:     return true;
        case TelephonyManager.NETWORK_TYPE_GSM:      return true;
        case TelephonyManager.NETWORK_TYPE_HSDPA:    return true;
        case TelephonyManager.NETWORK_TYPE_HSPA:     return true;
        case TelephonyManager.NETWORK_TYPE_HSPAP:    return true;
        case TelephonyManager.NETWORK_TYPE_HSUPA:    return true;
        case TelephonyManager.NETWORK_TYPE_IDEN:     return true;
        case TelephonyManager.NETWORK_TYPE_IWLAN:    return true;
        case TelephonyManager.NETWORK_TYPE_LTE:      return true;
        //case TelephonyManager.NETWORK_TYPE_NR:     return true;       // Not supported by my API
        case TelephonyManager.NETWORK_TYPE_TD_SCDMA: return true;
        case TelephonyManager.NETWORK_TYPE_UMTS:     return true;

        // Return false for unacceptable networks, UNKNOWN id no network e.g. airplane mode.
        case TelephonyManager.NETWORK_TYPE_UNKNOWN: return false;

        // Future unknown network types, handle as you please.
        default: return false;
    }
Jan Strom
  • 3
  • 1
Jan Strom
  • 11
  • 1
  • Hi Jan, Welcome to SO. You can provide answers in more understandable manner for others to grasp well. – Jacks Dec 05 '19 at 21:32
0

Try using following code to check if device is connected to internet or not.

    ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = conMgr.getActiveNetworkInfo();
    if (netInfo == null) {

        Toast.makeText(this, "Please turn on Internet ", Toast.LENGTH_SHORT).show();

    } else {
        //do what you want
    }
Kishan Thakkar
  • 429
  • 4
  • 11
0

You need to use Network Callback.

try {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkRequest.Builder builder = new NetworkRequest.Builder();

    connectivityManager.registerNetworkCallback(builder.build(),new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(Network network) {
                    Variables.isNetworkConnected = true; // Global Static Variable
                }
                @Override
                public void onLost(Network network) {
                    Variables.isNetworkConnected = false; // Global Static Variable
                }
            }

    );
    Variables.isNetworkConnected = false;
}catch (Exception e){
    Variables.isNetworkConnected = false;
}

Variables.isNetworkConnected - Here I used a Global Static Variable, So I can use it to access the network state in anyware of the application.

Please refer this gist for full code implementation.