1

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.

ganjaam
  • 1,030
  • 3
  • 17
  • 29
  • 1
    Have you tried removing the `addTransportType(NetworkCapabilities.TRANSPORT_WIFI)` and `addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)`? Maybe the emulator considers its internet connection to not be one of transport types `TRANSPORT_WIFI` or `TRANSPORT_CELLULAR`. The capability `NET_CAPABILITY_INTERNET` should still ensure that the connection is working and has access to the internet no matter what the transport type is. – sweak Feb 14 '23 at 11:27
  • 1
    @sweak it works. please add it in answer so that I can mark it as accepted. – ganjaam Feb 15 '23 at 03:38
  • also, adding `.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)` also works. – ganjaam Feb 15 '23 at 03:44

1 Answers1

1

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();
}
sweak
  • 1,369
  • 2
  • 6
  • 21