Tengo una aplicación implementada que falla en Android 9. Parte de su función es configurar un módulo a través de una red de punto de acceso para permitir que ese módulo se conecte a la red doméstica de los usuarios.

Tengo un código que detecta y se conecta a la red WIFI correcta, pero cuando intento abrir un socket en el dispositivo, falla, solo en Android 9 y solo si los datos móviles están habilitados. Si deshabilito manualmente los datos móviles en el dispositivo, todo funciona bien.

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;
}

He intentado esto con y sin la Proxy.NO_PROXY y con y sin la llamada bind(). Si falta la llamada de vinculación, el error implica que el socket está intentando conectarse a través de la red celular. (Nota: activity.logContent() es un registro en pantalla, por lo que es más fácil ver lo que sucede cuando no está conectado a un depurador).

Alguna idea de lo que va mal?

2
Stephen Orr 9 may. 2019 a las 22:51

3 respuestas

La mejor respuesta

Después de unos días de imprecaciones, creo que he llegado a la identificación del problema y, por lo tanto, a la solución:

El problema se produce debido a algunos cambios en la versión de Android (supongo que es 9.0 incluso si se han producido otros cambios en la API 21), en particular en la creación del socket, si el sistema detecta que hay una red "mejor" (acceso a internet, señal alta, etc., etc.) la creación de socket se refiere a esa red y ya no a la red wifi que desea.

Busqué formas de forzar la creación del socket en la red wifi (que es la red que quiero) y la única forma que encontré es esta:

Simplemente en lugar de:

Socket sock = nueva Socket ();

Hacer:

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();
                            }
                        }
                    }
            }

Prácticamente explore las redes presentes en el dispositivo y cuando encuentre su wifi activo no hará nada más que aprovechar esta función para obtener el socket correcto con seguridad:

getSocketFactory (). createSocket ()

¡Ahora tienes el enchufe de trabajo!

En mi caso, ahora funciona perfectamente, si alguien encuentra mejores soluciones, es bienvenido, pero por ahora es la única forma que he encontrado para que todo funcione como en la versión anterior de Android.

1
Bronz 19 ago. 2019 a las 04:16

En Android 9 hay una configuración de seguridad sobre la red: configuración de seguridad de Android

Agregar su dominio en network_security_config podría resolver su problema. Tenía esto en mi 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>
1
StoneLam 10 may. 2019 a las 02:55

No estoy seguro de la razón exacta de por qué sucede esto. Sin embargo, cuando enciende sus datos móviles y solo está conectado a Internet usando sus datos móviles (considerando que su wifi está apagado), obtiene la dirección IP de la red celular que ya no está conectada en su red doméstica. Por lo tanto, es trivial esperar tales escenarios de tiempo de espera, porque no puede llegar a las direcciones IP privadas de su red doméstica a partir de 192.168.....

Ahora mi confusión es que, incluso si los datos móviles están activados, y tanto los datos móviles como los wifi están activados al mismo tiempo, el dispositivo debe conectarse a wifi como un comportamiento predeterminado.

Por lo tanto, me gustaría sugerirle que verifique lo siguiente.

  • Android 9 (Pie) presenta Preferencia de wifi, que impide conectarse automáticamente a redes públicas. Puede considerar verificar la configuración.
  • Verifique la dirección IP de su dispositivo y verifique si tiene alguna dirección IP que comience con 192.168..... Si no es así, definitivamente, está obteniendo su dirección IP de su red celular y, por lo tanto, no puede alcanzar sus direcciones IP privadas de la red doméstica.
1
Reaz Murshed 10 may. 2019 a las 05:36