Cualquier app que tenga el permiso INTERNET puede acceder a los dispositivos de una red de área local (LAN).
Esto facilita que las apps se conecten a dispositivos locales, pero también tiene implicaciones de privacidad, como formar una huella digital del usuario y ser un proxy de ubicación.
El proyecto de protecciones de red local tiene como objetivo proteger la privacidad del usuario restringiendo el acceso a la red local detrás de un nuevo permiso de tiempo de ejecución.
Impacto
A partir de Android 17 (nivel de API 37), se aplican protecciones de red local para las apps que se orientan a Android 17 o versiones posteriores. La configuración anterior de habilitación de Android 16 dejó de estar disponible. Consulta Aplicación de medidas por incumplimiento en Android 17 para conocer los requisitos de implementación actuales.
Las apps se verán afectadas si acceden a la red local del usuario con lo siguiente:
- Uso directo o de biblioteca de sockets sin procesar en direcciones de red locales, por ejemplo,
Multicast DNS (mDNS)oSimple Service Discovery Protocol (SSDP). - Uso de clases a nivel del framework que acceden a la red local, por ejemplo,
NsdManager
Detalles del impacto
El tráfico hacia y desde una dirección de red local requiere permiso de acceso a la red local. En la siguiente tabla, se muestran algunos casos comunes:
| App Low Level Network Operation | Se requiere permiso de red local |
|---|---|
| Establece una conexión TCP saliente | sí |
| Acepta una conexión TCP entrante | sí |
| Envío de una transmisión de unidifusión, multidifusión o difusión de UDP | sí |
| Recibir una transmisión de unidifusión, multidifusión o difusión UDP entrante | sí |
Estas restricciones se implementan en lo profundo de la pila de red y, por lo tanto,
se aplican a todas las APIs de red. Esto incluye los sockets creados en la plataforma o el código administrado, las bibliotecas de redes como Cronet y OkHttp, y cualquier API implementada sobre ellas. Para intentar resolver los servicios de la red local que tienen un sufijo .local, se requiere el permiso de red local.
Excepciones a las reglas anteriores:
- Si el servidor DNS de un dispositivo está en una red local, el tráfico hacia o desde él (en el puerto 53) no requiere permiso de acceso a la red local.
- Las aplicaciones que usan el selector de salida como su selector integrado en la app no necesitarán permisos de red local (se proporcionarán más instrucciones en una versión posterior).
Aplicación de medidas por incumplimiento en Android 17
A partir de Android 17, las protecciones de red local son obligatorias y se aplican a las apps orientadas a Android 17 o versiones posteriores.
| Aspecto | Android 16 | Android 17 |
|---|---|---|
| SDK de destino | 36 | 37 o superior |
| Permiso | Se usó NEARBY_WIFI_DEVICES de forma temporal | ACCESS_LOCAL_NETWORK |
| Acceso predeterminado | El acceso a la red local está abierto | La red local está bloqueada de forma predeterminada para todas las apps que actualizan su SDK de destino |
| Grupo de permisos | Forma parte del grupo de permisos NEARBY_DEVICES existente | |
Para verificar que la funcionalidad de la app no se vea afectada después de la aplicación de la política, las aplicaciones que se orienten al SDK 37 o versiones posteriores deben adoptar una de las siguientes rutas de acceso para administrar el acceso a la red local:
Ruta A: Usa selectores que preservan la privacidad
Para las tareas de descubrimiento y conexión mediadas por el sistema, usa selectores para evitar solicitar el permiso de tiempo de ejecución amplio por completo. Usa los siguientes selectores según tu caso de uso:
- Transmisión de contenido multimedia: Las aplicaciones que admiten Google Cast pueden usar la función de selector de salida. Esto permite que los desarrolladores dejen que los usuarios seleccionen dispositivos de transmisión específicos sin que la app deba solicitar el permiso amplio
ACCESS_LOCAL_NETWORK. - Conectividad general: El
NsdManagerincluye un selector de servicios ejecutado por el sistema para el descubrimiento de mDNS. En lugar de que la app analice toda la red, el sistema muestra un diálogo que permite al usuario seleccionar un solo dispositivo al que la app puede acceder.
val discoveryRequest = DiscoveryRequest.Builder("_http._tcp")
.setFlags(DiscoveryRequest.FLAG_SHOW_PICKER)
.build()
nsdManager.registerServiceInfoCallback(discoveryRequest, executor, object : NsdManager.ServiceInfoCallback {
override fun onServiceUpdated(serviceInfo: NsdServiceInfo) {
// Handle the user-selected and discovered service
// NsdServiceInfo.getHostAddresses() can now be connected to
// without ACCESS_LOCAL_NETWORK permission
}
})
Ruta B: Solicita permiso de tiempo de ejecución (acceso amplio)
Esta ruta de acceso es obligatoria para casos de uso complejos, como la automatización del hogar o la administración de dispositivos de IoT, que necesitan un acceso amplio y persistente a la red local.
Declara el permiso en el manifiesto: Declara de forma explícita
ACCESS_LOCAL_NETWORKen elAndroidManifest.xml.Solicita permiso durante el tiempo de ejecución: Antes de intentar acceder a la red local, las aplicaciones deben verificar si se otorgó el permiso. De lo contrario, deben llamar a
Activity.requestPermission()para activar el mensaje estándar del sistema.Situación de otorgamiento previo: El permiso
ACCESS_LOCAL_NETWORKforma parte del grupo de permisosNEARBY_DEVICES. Si un usuario ya otorgó otro permiso en este grupo (como los permisos de Bluetooth), no se le volverá a solicitar el acceso a la red local.Manejo de rechazos y revocaciones: Las apps deben manejar correctamente los casos en los que el usuario rechaza la solicitud o revoca el permiso más adelante en la configuración del sistema. En esos casos, se bloqueará el tráfico de red local.
Estrategia de restablecimiento del contador de solicitudes de permiso
La plataforma implementa una estrategia de restablecimiento de contadores que aborda situaciones en las que el rechazo previo de una app del grupo de permisos NEARBY_DEVICES (que ahora incluye ACCESS_LOCAL_NETWORK) impidió que la app solicitara el permiso después de presentar adecuadamente su justificación. Este mecanismo
otorga oportunidades adicionales para que la app invoque la API de requestPermission(),
lo que restablece de forma efectiva el recuento de denegaciones para el permiso
ACCESS_LOCAL_NETWORK. Esto permite una reactivación más matizada con el usuario,
especialmente cuando la denegación inicial se produjo antes de que la app pudiera transmitir la
necesidad de acceso a la red local para su funcionalidad principal.
Modelo de permisos divididos
El permiso de red local utiliza una estrategia de migración de permisos divididos para controlar las aplicaciones nuevas y heredadas de manera diferente, según el SDK de destino
| Categoría | Nivel de SDK objetivo | Comportamiento del acceso a la red local | Acción requerida del desarrollador |
|---|---|---|---|
| Apps nuevas o actualizadas | >= 37 (Android 17) | Bloqueado de forma predeterminada | Declara y solicita el permiso de tiempo de ejecución ACCESS_LOCAL_NETWORK |
| Apps heredadas | < 37 | Las apps con el permiso INTERNET reciben un otorgamiento de permiso implícito para ACCESS_LOCAL_NETWORK, lo que les permite conservar el acceso. Esto es temporal y se bloqueará de forma predeterminada una vez que la app aumente el SDK de destino a 37 |
No es necesario realizar cambios en el código de inmediato. No solicites ACCESS_LOCAL_NETWORK durante el tiempo de ejecución antes de orientar la app al SDK 37. |
Estrategia de LNP por caso de uso
Transmisión: Para las funciones de transmisión de contenido multimedia, la estrategia más adecuada y que preserva la privacidad es usar el selector de salida. Este método permite que el sistema controle el descubrimiento y la conexión de la red local en nombre del usuario, lo que elimina la necesidad de que la app solicite el permiso
ACCESS_LOCAL_NETWORK.Navegadores: El manejo de errores requiere diferentes enfoques según el protocolo. Los errores de UDP generan el código de error
EPERM. Para las conexiones TCP, los navegadores deben usar la API de NDKandroid_getnetworkblockedreason(int sockFd)para determinar si la LNP bloqueó un paquete. Esta API devuelveANDROID_NETWORK_BLOCKED_REASON_LNP.Otros casos de uso (por ejemplo, IoT): Las aplicaciones que encuentran dispositivos con mDNS deben usar
android.net.nsd.DiscoveryRequest#FLAG_SHOW_PICKER, que permite encontrar dispositivos sin el permiso, yNsdManager#registerServiceInfoCallback/NsdManager#resolveServicepara obtener direcciones IP. Las conexiones a las direcciones IP obtenidas de esta manera no requieren el permisoACCESS_LOCAL_NETWORK.
En el caso de las aplicaciones que requieren comunicación directa con la red local y no pueden
usar selectores mediados por el sistema, el enfoque sugerido es usar la estrategia de restablecimiento del contador de permisos
cuando se orientan a Android 17 (SDK 37) o versiones posteriores. Si el usuario revoca el permiso ACCESS_LOCAL_NETWORK, este mecanismo proporciona oportunidades adicionales para que la app vuelva a solicitar el permiso, lo que permite que los desarrolladores presenten una justificación más clara para el usuario.
Orientación para Android 16 (obsoleto)
Para habilitar las restricciones de red local en Android 16, haz lo siguiente:
- Escribe en la memoria flash del dispositivo una compilación con Android 16 Beta 3 o una versión posterior
- Instala la app que se probará
Cómo activar o desactivar la configuración de Appcompat con adb
adb shell am compat enable RESTRICT_LOCAL_NETWORK <package_name>Reinicia el dispositivo
Ahora, el acceso de tu app a la red local está restringido, y cualquier intento de acceder a la red local genera errores de socket.
Si usas APIs que realizan operaciones de red local fuera del proceso de tu app (por ejemplo, NsdManager), no se verán afectadas durante la habilitación.
Para restablecer el acceso, debes otorgarle a la app permiso para NEARBY_WIFI_DEVICES.
- Asegúrate de que la app declare el permiso
NEARBY_WIFI_DEVICESen sumanifest. - Ve a Configuración > Apps > [Nombre de la app] > Permisos > Dispositivos cercanos > Permitir
Ahora, se debería restablecer el acceso de tu app a la red local, y todas tus situaciones deberían funcionar como antes de habilitar la app. Así se ve afectado el tráfico de red de la app.
| Permiso | Solicitud de LAN saliente | Solicitud de Internet entrante o saliente | Solicitud de LAN entrante |
|---|---|---|---|
| Concedido | Works | Works | Works |
| No otorgado | Errores | Works | Errores |
Usa el siguiente comando para desactivar la configuración de Appcompat:
adb shell am compat disable RESTRICT_LOCAL_NETWORK <package_name>
Errores
Si falla una solicitud de acceso a la red local debido a que falta un permiso, haz lo siguiente:
Por lo general, las conexiones TCP generarán un error de tiempo de espera.
Los errores de UDP y las denegaciones de permisos generales suelen generar un código de error EPERM.
Errores
Envía errores y comentarios sobre los siguientes temas:
- Discrepancias en el acceso a la LAN (crees que un acceso determinado no debería considerarse acceso a la "red local")
- Errores en los que se debería bloquear el acceso a la LAN, pero no se hace
- Errores en los que el acceso a la LAN no debería estar bloqueado, pero lo está
Los siguientes elementos no deberían verse afectados por este cambio:
- Acceso a Internet
- Red móvil