Desarrolla para redes satelitales restringidas

Algún día, las redes satelitales serán lo suficientemente sólidas como para funcionar como redes normales y trabajar sin problemas con todos los casos de uso de las apps, pero, por ahora, los datos en estas redes son un recurso escaso. Una red satelital con restricciones en el uso de datos se denomina red satelital restringida.

Debido a estas restricciones, las apps para Android no usan estas redes de forma predeterminada. Si quieres que tu app funcione en redes satelitales con restricciones, debes identificar tu app como optimizada para el uso de datos satelitales y adaptar los casos de uso de tu app para conservar recursos cuando se conecte a una red satelital con restricciones.

Adapta los casos de uso de tu app

Todo lo que debes hacer para permitir que tu app acceda a redes satelitales restringidas es habilitar la opción, pero es posible que debas realizar más cambios para optimizar el comportamiento de tu app y usar los recursos de red limitados de manera responsable. Estos son algunos aspectos que debes tener en cuenta cuando optimizas el uso de datos restringido:

  • Las redes satelitales operan en condiciones mucho más limitadas que las redes terrestres LTE/5G, caracterizadas por un menor rendimiento y una mayor latencia. Si bien, en general, recomendamos minimizar el uso de datos por motivos de confiabilidad, cada app es única. Debes evaluar tus casos de uso específicos para determinar si tus estrategias actuales de optimización de datos proporcionan una experiencia del usuario aceptable en estos entornos restringidos.
  • Decide si tu app es apta para usarse en redes con restricciones. En ningún caso, algunas apps son adecuadas para redes con limitaciones de datos. Por ejemplo, las apps con un gran ancho de banda, como las de transmisión de video por Internet, deben evaluar sus mecanismos de compresión de datos y entrega de contenido para garantizar una experiencia del usuario funcional. Si es inevitable una experiencia degradada debido a limitaciones de datos, la app debe realizar las siguientes acciones:
    1. Es posible que las apps decidan no usar redes satelitales en absoluto, aunque podrían identificar la presencia de una red satelital y avisarle al usuario que no funcionarán en la red limitada existente.
    2. Identifica casos de uso específicos para limitar o modificar. Algunas funciones de tu app podrían ser más adecuadas para condiciones de datos limitados que otras. Por ejemplo, las operaciones de bajo ancho de banda, como el envío de mensajes de texto, son muy confiables. Sin embargo, las operaciones de alto ancho de banda, como la carga de videos en HD sin comprimir, pueden experimentar un almacenamiento en búfer o fallas significativos. Te recomendamos que implementes la transmisión de tasa de bits adaptable o una compresión sólida para estas funciones exigentes. Esto es similar a la forma en que muchas apps cambian su comportamiento cuando se encuentran en roaming.
    3. Adapta la forma en que tu app usa los recursos de red. Las redes restringidas funcionan mejor cuando las apps realizan operaciones de red en ráfagas y pasan la mayor parte del tiempo sin usar la red. La latencia variable puede dificultar la comunicación síncrona en tiempo real.

También hay cambios específicos que debes realizar si tu app usa lógica de redes compleja o Firebase Cloud Messaging.

Identificarse como optimizado para redes con restricciones

Para identificar tu app como optimizada para redes restringidas y habilitar su uso, actualiza tu archivo de manifiesto de la app con un elemento <meta-data> de la siguiente manera:

<meta-data android:name="android.telephony.PROPERTY_SATELLITE_DATA_OPTIMIZED"
          android:value="PACKAGE_NAME" />

Este elemento permite que tu app use una red satelital restringida cuando es la única red disponible. También notifica al sistema que tu app está optimizada para redes con limitaciones, lo que ayuda a los usuarios a descubrirla, ya que se muestra entre las apps compatibles con satélites en la app de configuración.

Cambiar el comportamiento en condiciones de datos restringidos

Si necesitas cambiar el comportamiento de tu app cuando se usa una red restringida o si tu app tiene lógica preexistente que usa ConnectivityManager para administrar el uso de la red, deberás realizar algunos cambios en el flujo de red.

Detecta condiciones de datos restringidos

El objeto NetworkCapabilities que se usa para las solicitudes de red incluye un bit NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED que se establece de forma predeterminada en todas las redes y se quita en las redes con limitaciones de ancho de banda. Para determinar si una red tiene limitaciones de ancho de banda, verifica si tiene la capacidad NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED.

Trabaja con redes restringidas

Los objetos NetworkRequest también incluyen la capacidad NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED de forma predeterminada. Quita esta capacidad para indicar que se aceptan las redes restringidas.

Cuando detectes que te conectaste a una red restringida, puedes adaptar las funciones de tu app según sea necesario:

Kotlin

val HandlerThread = HandlerThread("SatelliteNetworkMonitor"
handlerThread.start()
val handler = Handler(handlerThread.getLooper())

// Make the network request.
val request = NetworkRequest.Builder()
    .addCapability(NET_CAPABILITY_INTERNET
    .removeCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)
    .build()

// Register for the callback.
val callback = NetworkCallback() {
    override fun onCapabilitiesChanged(net: Network, nc: NetWorkCapabilities) {
        updateAppUseCases(net, nc)
    }

    fun updateAppUseCases(net: Network, nc: NetworkCapabilities) {
        if (!nc.hasCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED) ||
             nc.hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)) {
            // Adapt to constrained network or disable heavy data usage features.
            ...
        } else {
            // Revert to unconstrained behavior.
            ...
        }
    }
}
// Where cm is your ConnectivityManager object:
cm.registerBestMatchingNetworkCallback(request, callback, handler)

Java

HandlerThread handlerThread = new HandlerThread("SatelliteNetworkMonitor");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());

// Make the network request.
NetworkRequest request = new NetworkRequest.Builder()
    .addCapability(NET_CAPABILITY_INTERNET)
    .removeCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)
    .build();

// Register for the callback.
NetworkCallback callback = new NetworkCallback() {
    @Override
    public void onCapabilitiesChanged(Network net, NetworkCapabilities nc) {
        updateAppUsecases(net, nc);
    }
    private void updateAppUsecases(Network net, NetworkCapabilities nc) {
        if (!nc.hasCapability(NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED) || nc.hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)) {
            // Adapt to constrained network or disable heavy data usage features.
            ...
        } else {
            // Revert to unconstrained behavior.
            ...
        }
    }
};
// Where cm is your ConnectivityManager object:
cm.registerBestMatchingNetworkCallback(request, callback, handler);

Cómo recibir mensajes de FCM en redes con restricciones

Si tu app usa Firebase Cloud Messaging (FCM) para recibir mensajes de un servidor de apps, puedes indicar que se debe entregar un mensaje específico incluso en redes con restricciones. Para ello, incluye la marca bandwidth_constrained_ok cuando pases el mensaje al servidor de FCM:

{
  "message":{
    "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!"
    }
    "android": {
       "bandwidth_constrained_ok": true
    }
  }
}

Si un mensaje no incluye esta marca, el servidor de FCM solo lo entrega cuando el dispositivo está conectado a través de una red sin restricciones.