Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Network Test on API 29 - Java
package com.example.simplenetwork;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.util.Log;
import androidx.annotation.NonNull;
public class CheckNetwork {
private Context context;
public CheckNetwork(Context context) {
this.context = context;
}
void registerDefaultNetworkCallback(){
try {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
assert connectivityManager != null;
connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback(){
@Override
public void onAvailable(@NonNull android.net.Network network) {
super.onAvailable(network);
GlobalVars.isNetworkConnected = true;
Log.d("FLABS:", "onAvailable");
}
@Override
public void onLost(@NonNull android.net.Network network) {
super.onLost(network);
GlobalVars.isNetworkConnected = false;
Log.d("FLABS:", "onLost");
}
@Override
public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {
super.onBlockedStatusChanged(network, blocked);
Log.d("FLABS:", "onBlockedStatusChanged");
}
@Override
public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities);
Log.d("FLABS:", "onCapabilitiesChanged");
}
@Override
public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) {
super.onLinkPropertiesChanged(network, linkProperties);
Log.d("FLABS:", "onLinkPropertiesChanged");
}
@Override
public void onLosing(@NonNull Network network, int maxMsToLive) {
super.onLosing(network, maxMsToLive);
Log.d("FLABS:", "onLosing");
}
@Override
public void onUnavailable() {
super.onUnavailable();
Log.d("FLABS:", "onUnavailable");
}
});
} catch (Exception e) {
Log.d("FLABS: Exception in registerDefaultNetworkCallback", "hello");
GlobalVars.isNetworkConnected = false;
}
}
void registerNetworkCallback(){
try {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder = new NetworkRequest.Builder();
assert connectivityManager != null;
connectivityManager.registerNetworkCallback(builder.build(), new ConnectivityManager.NetworkCallback(){
@Override
public void onAvailable(@NonNull android.net.Network network) {
super.onAvailable(network);
GlobalVars.isNetworkConnected = true;
Log.d("FLABS:", "onAvailable");
}
@Override
public void onLost(@NonNull android.net.Network network) {
super.onLost(network);
GlobalVars.isNetworkConnected = false;
Log.d("FLABS:", "onLost");
}
@Override
public void onBlockedStatusChanged(@NonNull Network network, boolean blocked) {
super.onBlockedStatusChanged(network, blocked);
Log.d("FLABS:", "onBlockedStatusChanged");
}
@Override
public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities);
Log.d("FLABS:", "onCapabilitiesChanged");
}
@Override
public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) {
super.onLinkPropertiesChanged(network, linkProperties);
Log.d("FLABS:", "onLinkPropertiesChanged");
}
@Override
public void onLosing(@NonNull Network network, int maxMsToLive) {
super.onLosing(network, maxMsToLive);
Log.d("FLABS:", "onLosing");
}
@Override
public void onUnavailable() {
super.onUnavailable();
Log.d("FLABS:", "onUnavailable");
}
});
} catch (Exception e) {
Log.d("FLABS: Exception in registerNetworkCallback", "hello");
GlobalVars.isNetworkConnected = false;
}
}
}
package com.example.simplenetwork;
public class GlobalVars {
public static int counter = 0;
public static boolean isNetworkConnected = false;
}
package com.example.simplenetwork;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Register NetworkCallback -- need to call this when activity starts
CheckNetwork network = new CheckNetwork(getApplicationContext());
/*
* registerNetworkCallback() is available from API-21 and above
* But it will show status of all available network. Hence you would
* to query onCapabilitiesChanged() to make sure your intended network is active or not.
*/
// network.registerNetworkCallback();
/*
* network.registerDefaultNetworkCallback() is available from API-24
* Unlike its counterpart, it will only register status of current active network
* Hence no need to check with onCapabilitiesChanged(). But downside is that it
* is available since API-24 while current recommendation (in 2019) is to maintain
* minimum support for API-23 Marshmallo.
*/
network.registerDefaultNetworkCallback();
final TextView text = findViewById(R.id.test_message);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@SuppressLint({"SetTextI18n", "DefaultLocale"})
@Override
public void onClick(View view) {
GlobalVars.counter++;
if (GlobalVars.isNetworkConnected) {
text.setText(String.format("Counter is %d, And network is Connected", GlobalVars.counter));
} else {
text.setText(String.format("Counter is %d, And network is Not Connected", GlobalVars.counter));
}
}
});
}
}
@Abhinav1217

This comment has been minimized.

Copy link
Owner Author

@Abhinav1217 Abhinav1217 commented Nov 23, 2019

Switch logcat to debug, Clean existing logs, and filter by FLABS to see stuff triggered by my code.

@Abhinav1217

This comment has been minimized.

Copy link
Owner Author

@Abhinav1217 Abhinav1217 commented Nov 26, 2019

https://gist.github.com/PasanBhanu/730a32a9eeb180ec2950c172d54bb06a for complete debug log and other discussion. He is also the original guy for this gist.

@kalirajp91

This comment has been minimized.

Copy link

@kalirajp91 kalirajp91 commented Feb 15, 2020

Thank u abhinav... it was working

@shamshadpattani

This comment has been minimized.

Copy link

@shamshadpattani shamshadpattani commented Feb 22, 2020

is it support Min sdk is 19

@Abhinav1217

This comment has been minimized.

Copy link
Owner Author

@Abhinav1217 Abhinav1217 commented Feb 23, 2020

@shamshadpattani
registerDefaultNetworkCallback() was added in API 24, registerNetworkCallback() was added in API 21. I am currently using try/catch in my network class to use registerDefaultNetworkCallback() for api24 and above, and fallback to older NetworkInfo method for anything below it.

@shamshadpattani

This comment has been minimized.

Copy link

@shamshadpattani shamshadpattani commented Feb 23, 2020

thank u bro

@saiga006

This comment has been minimized.

Copy link

@saiga006 saiga006 commented Nov 25, 2020

Hi @Abhinav1217,

   `
     public static boolean isDeviceConnected = false;

     // network callback code lies here

     public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
        
        super.onCapabilitiesChanged(network, networkCapabilities);

        Log.d(TAG," capabilities for the default network is " + networkCapabilities.toString());
        Log.d(TAG," does it have validated network connection internet presence : "
                + networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                + " is it validated "
                + networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED));
        if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {

            if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
                && !isDeviceConnected) {
                isDeviceConnected = true;
            } else if (!networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
                    && isDeviceConnected) {
                // handles the scenario when the internet is blocked by ISP,
                // or when the dsl/fiber/cable line to the router is disconnected
                isDeviceConnected = false;
                Log.d(TAG, " Internet Connection is lost temporarily for network: " + network.toString());
            }
        }
    }

    public void onLost(NonNull Network network) {
        super.onLost(network);
        if (isDeviceConnected) {
            isDeviceConnected = false;
            Log.d(TAG, "Connection is lost for network: " + network.toString());
        }
    }

`

I have maintained a state variable, to check whether a device has valid internet connection (isDeviceConnected -- static global variable)
based on NetworkCapabilities.NET_CAPABILITY_VALIDATED (this will say whether a network has active internet connection).

I was successful in receiving the network callback events when wifi was off, toggled on, or if the wifi has internet or in no internet scenarios.

@ksanbormukhim

This comment has been minimized.

Copy link

@ksanbormukhim ksanbormukhim commented Jan 31, 2021

How do i unregistered this callback?

@Abhinav1217

This comment has been minimized.

Copy link
Owner Author

@Abhinav1217 Abhinav1217 commented Feb 1, 2021

@ksanbormukhim

How do i unregistered this callback?

From android documentation
Registers to receive notifications about changes in the system default network. The callbacks will continue to be called until either the application exits or unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback) is called.

There is a limit of 100 pending callbacks per app imposed by OS. Unless there is a leak in your code, it is almost impossible to reach that because most of the time Unregistration is automatically handled when Lifecycle ends. And also here you can see that we are using a static singleton to reuse object. But if you are really unsure what will your code do, you can unregisterNetworkCallback in your Activitiy onDestroy() . But I wont recommend that because that means that when next activity loads, you would register it again and destroy it again which is performance regression. Follow the clean architecture code principles.

Only place I have actually used unregister callback is quit menu within my app. But in reality, its just redundant because OS automatically handles it when app is closed. (See docs I linked).

The original gist from pranas has more detailed discussion on how to handle network.

@ksanbormukhim

This comment has been minimized.

Copy link

@ksanbormukhim ksanbormukhim commented Feb 2, 2021

@Abhinav1217 thanks for the clarification

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment