针对受限的卫星网络进行开发

卫星网络终有一天会足够强大,能够像普通网络一样运行,并与所有应用用例无缝协作;但目前,这些网络上的数据是稀缺资源。对数据用量有限制的卫星网络称为受限卫星网络。

由于这些限制,Android 应用默认不会使用这些网络。如果您希望应用在受限的卫星网络上运行,则必须将应用标识为已针对卫星数据用量进行优化,并调整应用的用例,以便在连接到受限的卫星网络时节省资源。

调整应用的使用场景

若要允许应用访问受限卫星网络,您只需选择启用即可,但您可能需要做出进一步更改,以优化应用的行为,从而负责任地使用有限的网络资源。在针对受限的数据用量进行优化时,请注意以下事项:

  • 卫星网络在比地面 LTE/5G 网络更受限的条件下运行,其特点是吞吐量较低且延迟较高。虽然出于可靠性考虑,我们通常建议尽量减少数据用量,但每个应用都是独一无二的。您应评估自己的具体用例,以确定当前的数据优化策略是否能在这些受限环境中提供可接受的用户体验。
  • 确定您的应用是否适合在受限网络中使用。在任何情况下,某些应用都不适合在数据受限的网络中使用。例如,高带宽应用(如视频串流应用)应评估其数据压缩和内容传送机制,以确保提供实用的用户体验。如果由于数据限制而不可避免地导致体验降级,应用应采取以下措施:
    1. 应用可能会选择完全不使用卫星网络,但它们仍可以识别卫星网络的存在,并告知用户它们无法在现有的受限网络上运行。
    2. 确定要限制或修改的具体用例。应用的某些功能可能比其他功能更适合在数据受限的情况下使用。例如,发送短信等低带宽操作非常可靠。不过,高带宽操作(例如上传未压缩的高清视频)可能会遇到严重的缓冲或失败。我们建议针对这些要求较高的功能实现自适应比特率流式传输或强大的压缩功能。这与许多应用在漫游时更改行为的方式类似。
    3. 调整应用使用网络资源的方式。当应用突发性地执行网络操作,并且大部分时间不使用网络时,受限网络的效果最佳。可变延迟时间可能会使实时同步通信变得困难。

如果您的应用使用复杂的网络逻辑或 Firebase Cloud Messaging,您还需要进行一些特定的更改。

自行标识为针对受限网络进行了优化

如需将您的应用标识为已针对受限网络进行优化并选择使用这些网络,请使用 <meta-data> 元素更新应用清单文件,如下所示:

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

此元素允许您的应用在只有受限卫星网络可用时使用该网络。它还会通知系统,您的应用已针对受限网络进行了优化,从而在设置应用中将其列为支持卫星通信的应用,帮助用户发现该应用。

在数据受限的情况下更改行为

如果您需要在应用使用受限网络时更改其行为,或者您的应用具有使用 ConnectivityManager 管理网络使用的预先存在的逻辑,则需要对网络流进行一些更改。

检测受限数据条件

用于网络请求的 NetworkCapabilities 对象包含一个 NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED 位,该位在所有网络上默认设置,并在带宽受限的网络上移除。您可以通过检查网络是否具有 NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED 功能来确定网络是否受带宽限制。

应对受限网络

默认情况下,NetworkRequest 对象还包含 NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED 功能。移除此功能可表明受限网络是可以接受的。

当您检测到已连接到受限网络时,可以根据需要调整应用的功能:

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 = object : NetworkCallback() {
    override fun onCapabilitiesChanged(net: Network, nc: NetworkCapabilities) {
        updateAppUseCases(net, nc)
    }

    fun updateAppUseCases(net: Network, nc: NetworkCapabilities) {
        // Check if the network is bandwidth-constrained or if the transport is satellite.
        // Checking for the satellite transport is to make sure that application
        // continue to have optimized behavior on satellite networks irrespective of whether
        // the NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED capability is set or not. This is
        // because the capability can be removed on an unconstraned satellite Network which only
        // means applications does not need to modify to get data access but should continue
        // to optimize for data usage.
        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 non optimized behavior for data usage.
            // ...
        }
    }
}
// Where cm is your ConnectivityManager object:
cm.registerBestMatchingNetworkCallback(request, callback, handler)

在受限网络上接收 FCM 消息

如果您的应用使用 Firebase Cloud Messaging (FCM) 从应用服务器接收消息,您可以在将消息传递到 FCM 服务器时添加 bandwidth_constrained_ok 标志,以指明即使在受限网络中也应传递特定消息:

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

如果消息不包含此标志,则 FCM 服务器仅在设备通过无限制网络连接时才传送该消息。