2

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?

Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
Stephen Orr
  • 291
  • 3
  • 7
  • please referer this link https://stackoverflow.com/questions/35152417/send-data-through-wifi-no-internet-when-mobile-data-on i having same issue – Utsav Thakkar Jun 07 '19 at 10:50

3 Answers3

1

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>
StoneLam
  • 370
  • 6
  • 11
  • Thanks for this suggestion, I actually already have that file, but the project is built against 19, so I'm not sure the permissions file is being used. Also I (believe?) you get a different error in that case (not a timeout, but a security error), and that doesn't explain why the code works when mobile data is turned off (thus forcing the socket to connect through Wifi?) – Stephen Orr May 10 '19 at 03:29
1

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.
Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
  • Thanks for pointing out the WiFi preference. The device we have also includes the ability to set specific apps to us or not use Mobile data. Changing these preferences doesn't have any impact. The localIpAddress() call on the device resolves to 192.168.17.2 which is the IP of the device's Access Point. – Stephen Orr May 10 '19 at 15:08
1

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.

Bronz
  • 217
  • 3
  • 7