Stephen Orr
Stephen Orr

Reputation: 301

Android 9 - Socket Connect TIMEOUT when Mobile data enabled

I have a deployed app that is failing on Android 9. Part of its function is to configure a module over an Access Point network to allow that that module to connect to the users home network.

I have code that detects and connects to the correct WIFI network, but when I attempt to open a socket to the device, it fails - only on Android 9 and only if mobile data is enabled. If I manually disable mobile data on the device everything runs fine.

Socket open() {
    Socket sock = new Socket(Proxy.NO_PROXY);
    try {
        sock.bind(new InetSocketAddress(localIpAddress(), 50000));
    } catch (IOException e) {
        activity.logContent("Warning: Failed to bind socket : " + e.toString());
    }
    try {
        sock.connect(new InetSocketAddress("192.168.17.1", 5555), (int)5000);
    } catch (IOException e) {
        // This catch fires when Mobile Data is on.
        activity.logContent("Connected to " + activity.mWifiManager.getConnectionInfo().getSSID());
        activity.logContent("Couldn't open socket : " + e.toString());
    }
    return sock;
}

I have tried this with and without the Proxy.NO_PROXY and with and without the bind() call. If the bind call is missing the error implies that the socket is attempting to connect over the cell network. (Note: activity.logContent() is an on-screen log so it is easier to see what is happening when not connected to a debugger).

Any ideas what is going wrong?

Upvotes: 2

Views: 2957

Answers (3)

Bronz
Bronz

Reputation: 217

After a few days of imprecations I believe I have come to the identification of the problem and therefore to the solution:

The problem occurs due to some changes in the version of android (I presume to be 9.0 even if other changes had occurred on API 21), in particular on the creation of the socket, if the system detects that there is a "better" network (access to internet, high signal, etc, etc) socket creation refers to that network and no longer to the wifi network you would like.

I looked for ways to force the creation of the socket on the wifi network (which is the network I want) and the only way I found is this:

Simply put instead of:

Socket sock = new Socket ();

Do:

ConnectivityManager connectivity = (ConnectivityManager) MyApp.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
                if (connectivity != null)
                {
                    for (Network network : connectivity.getAllNetworks())
                    {
                        NetworkInfo networkInfo = connectivity.getNetworkInfo(network);

                        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI)
                        {
                            if (networkInfo.isConnected())
                            {
                                Socket sock =  network.getSocketFactory().createSocket();
                            }
                        }
                    }
            }

Practically browse the networks present in the device and when you find your active wifi you do nothing but take advantage of this function to get the right socket for sure:

getSocketFactory().createSocket()

Now you have the working socket!

In my case it now works perfectly, if someone finds better solutions, it is welcome, but for now it is the only way I have found to make everything work as in the previous version of android.

Upvotes: 1

Reaz Murshed
Reaz Murshed

Reputation: 24211

I am not sure about the exact reason of why this is happening. However, when you are turning on your mobile data and you are only connected to the internet using your mobile data (considering your wifi is turned off), it gets the IP address from the cellular network which is no more connected in your home network. Hence, this is trivial to expect such timeout scenarios, because, it cannot reach the private IP addresses of your home network starting with 192.168.....

Now my confusion is that even if the mobile data is turned on, and both wifi and mobile data is turned on at the same time, the device should connect to the wifi as a default behavior.

Hence I would like to suggest you check the following.

  • Android 9 (Pie) introduces special Wifi preference, which prevents connecting to public networks automatically. You might consider checking the settings.
  • Please check the IP address of your device and check if it has some IP address starting with 192.168..... If not, then definitely, you are getting your IP address from your cellular network and hence it cannot reach your private IP addresses of the home network.

Upvotes: 1

StoneLam
StoneLam

Reputation: 400

In Android 9 there a security config about network: Android security config

Adding your domain in network_security_config might solve your problem. I had this in my network_security_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">119.xxx.xxx.xxx</domain>
    </domain-config>
</network-security-config>

Upvotes: 1

Related Questions