In order to get notified when the device connects/disconnects from internet, I took the following approach:
ConnectivityManager connectivityManager = activity.getSystemService(ConnectivityManager.class);
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(@NonNull Network network) {
super.onAvailable(network);
try {
activity.runOnUiThread(() -> {
tvNoInternet.animate().alpha(0f).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
MiscellaneousUtils.hideView(tvNoInternet, View.GONE);
}
});
behaviour.onConnected();
// behaviour is an interface named NetworkConnectionBehaviour (check the following snippet for its implementation)
});
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
@Override
public void onLost(@NonNull Network network) {
super.onLost(network);
try {
activity.runOnUiThread(() -> {
if (isInternetConnected(activity)) {
// check internet connection status because onLost() is called
// after onAvailable() when the device automatically switches
// internet connection from cellular to wifi
return;
}
tvNoInternet.animate().alpha(1f).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
MiscellaneousUtils.showView(tvNoInternet);
}
});
behaviour.onDisconnected();
});
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
};
try {
NetworkRequest networkRequest = getNetworkRequest();
// implementation of getNetworkRequest() is added in next snippet
connectivityManager.registerNetworkCallback(networkRequest, networkCallback);
} catch (Exception e) {
Toast.makeText(activity, "Unexpected interruption! please try again later", Toast.LENGTH_SHORT).show();
}
Interface NetowrkConnectionBehaviour:
public interface NetworkConnectionBehaviour {
void onConnected();
void onDisconnected();
}
Implementation of getNetworkRequest()
:
public static NetworkRequest getNetworkRequest() {
return new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build();
}
This approach is working in all physical devices and emulator of android studio.
However, if someone runs the app on Bluestacks 5 emulator, the callbacks of ConnectivityManager aren't called at all. And it does not produce any exception either.
Am I missing something here? Is there a different way to use ConnectivityManager for BlueStacks?
NOTE: It shows same behaviour for gameloop emulator too.
The solution is to remove transport types: TRANSPORT_WIFI
and TRANSPORT_CELLULAR
since the BlueStacks 5 Emulator does not recognize its connection to be one of those transport types.
The capability NET_CAPABILITY_INTERNET
will ensure that the connection is working and has access to the internet as per docs:
Indicates that this network should be able to reach the internet.
The code for the NetworkRequest
now should be as follows:
public static NetworkRequest getNetworkRequest() {
return new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
}