Una app Android no consigue resolver un nombre interno mientras el navegador del cliente VPN sí llega a él, y la misma compilación funciona en otro teléfono. La variable no es la URL. La variable es qué red puede usar el proceso de la app para resolver, y Android no garantiza que la VPN activa sea la que usan tus sockets. Haz estas comprobaciones en orden y detente cuando la instantánea del resolutor no coincida con tu suposición.

Paso 1: Demuestra en qué red está la app

Lee la visión de la propia app en lugar de la barra de estado. Desde ConnectivityManager obtén la red activa, sus LinkProperties , la lista de servidores DNS y el ajuste de DNS privado. Si la lista contiene el resolutor de la VPN, la app tiene un camino hacia él; si contiene el resolutor del Wi-Fi, el túnel no es la red predeterminada de ese proceso.

Un icono de VPN solo dice que existe un túnel. No dice que el proceso de la app se haya vinculado a él, y Android no siempre encamina la resolución de nombres por la red que parece activa. Las apps VPN locales que reenvían a otro dispositivo, las redes Wi-Fi sin internet y las compilaciones de fabricantes pueden dejar que una app pregunte al resolutor predeterminado en lugar de a los servidores del túnel.

Paso 2: Solicita el transporte VPN y vincula el proceso

Cuando la app deba usar el resolutor del túnel, solicita una red con el transporte VPN y vincula el proceso en la devolución de llamada, para que el código no adivine cuándo aparece la red:

val request = NetworkRequest.Builder()
    .addTransportType(NetworkCapabilities.TRANSPORT_VPN)
    .build()

connectivityManager.requestNetwork(request, object : NetworkCallback() {
    override fun onAvailable(network: Network) {
        val bound = connectivityManager.bindProcessToNetwork(network)
        Log.i(TAG, "bound to VPN network: " + bound)
    }
})

La llamada cambia la red predeterminada de todo el proceso, así que cada socket creado después la usa. Los sockets que ya existen conservan la red en la que se crearon, y por eso un grupo de conexiones abierto antes de la vinculación puede seguir resolviendo por la ruta antigua. El valor devuelto es un booleano, y un resultado false significa que la vinculación no se produjo; reinténtalo con un retraso breve y registra ambos intentos.

Paso 3: Limita la vinculación a lo que la necesita

La vinculación de todo el proceso es burda. La telemetría, las comprobaciones de actualización y los SDK de terceros también pasan al túnel, y si el túnel no tiene internet empiezan a fallar. Para una sola petición, usa la fábrica de sockets de la red y mantén el valor predeterminado del dispositivo para todo lo demás. Elige un modelo a propósito: una vinculación estrecha por conexión, o una vinculación de proceso con desvinculación explícita cuando la VPN desaparece.

Dos funciones del resolutor pueden vencer la vinculación sin ningún error. El DNS privado en modo estricto envía las consultas a un servidor DoT con nombre en lugar del resolutor de la red, y una app que incluye su propio cliente DNS-over-HTTPS evita por completo el resolutor del sistema. Comprueba ambas antes de concluir que la vinculación falló. Una consulta que nunca llega al servidor DNS de la VPN no aparecerá en ningún registro del lado del túnel.

Paso 4: No confíes en una restricción CONNECTED

La marca NetworkType.CONNECTED de WorkManager significa que hay una red conectada, y el transporte VPN la satisface incluso cuando el enlace Wi-Fi o móvil subyacente ha desaparecido. La tarea se ejecuta, cada petición falla y la política de reintentos la convierte en una tormenta que parece un error de planificación. El túnel es una red; la restricción nunca fue una comprobación de internet.

Comprueba la capacidad que el trabajo necesita de verdad, como el acceso a internet validado, y mantén una política de reintentos limitada con retroceso. Si el trabajo necesita un nombre interno, resuelve ese nombre en la red seleccionada antes de hacer el trabajo, y falla rápido con un error claro en lugar de repetir una petición que no puede tener éxito.

Paso 5: Registra las pruebas y vuelve a probar el rango

Registra los tipos de transporte de la red seleccionada, los servidores DNS de LinkProperties , si la vinculación devolvió true y el fallo exacto de la primera petición. Luego ejecuta un nombre interno y un nombre público bajo la misma vinculación. Esa pareja muestra si la app usó el resolutor del túnel o cayó en silencio al valor predeterminado del dispositivo, y esa es la diferencia que vive el usuario.

Repite en la versión de Android más antigua que admitas y en una versión actual. El comportamiento del resolutor que hace que la ruta predeterminada parezca correcta es justo donde difieren dispositivos y versiones, y una compilación que solo pasa en el dispositivo de prueba más nuevo no está verificada para el rango que distribuyes. adb shell dumpsys connectivityes una forma rápida de confirmar qué redes y capacidades informa el dispositivo mientras reproduces el fallo.

Artículos relacionados