registerDefaultNetworkCallback和registerNetworkCallback的区别。

32

我在更新我的Android应用程序至API 28时,发现了 registerDefaultNetworkCallbackregisterNetworkCallback

经过查看文档后,我无法找到注册“网络回调”和注册“默认网络回调”之间的区别。

什么情况下会使用哪个呢?

提前感谢 :)

7个回答

37
据我所了解,registerDefaultNetworkCallbackregisterNetworkCallback之间的区别仅在于定制方面。registerDefaultNetworkCallback(令人惊讶地)作为默认网络侦听器工作,而registerNetworkCallback则更具可配置性。例如:
    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    val builder = NetworkRequest.Builder()
    builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)

    val networkRequest = builder.build()
    connectivityManager.registerNetworkCallback(networkRequest, 
    object : ConnectivityManager.NetworkCallback () {
        override fun onAvailable(network: Network?) {
            super.onAvailable(network)
            Log.i("Test", "Network Available")
        }

        override fun onLost(network: Network?) {
            super.onLost(network)
            Log.i("Test", "Connection lost")
        }
    })

如果用户连接到蜂窝网络,onAvailable 将被调用(通过连接到 WiFi,它不会记录任何内容)。同样,当与蜂窝网络断开连接时,onLost 也是如此。

如果我们这样做:

    connectivityManager.registerDefaultNetworkCallback(object  : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network?) {
            super.onAvailable(network)
            Log.i("Test", "Default -> Network Available")
        }

        override fun onLost(network: Network?) {
            super.onLost(network)
            Log.i("Test", "Default -> Connection lost")
        }
    })

这两个函数是在用户连接(或断开连接)到/从网络时作为默认回调函数。网络可以是WiFi或蜂窝网络。

这只是一些非常基本的示例。当设置capabilitytransportType时,NetworkRequest可以具有许多配置选项。您可以在NetworkRequest的官方文档中了解更多信息。


谢谢你的回答。这段代码应该放在哪里?是在onCreate中吗? - xjcl
8
请注意,onAvailable 不会在主线程发生,因此任何 UI 更新都需要在 runOnUiThread { /* code */ } 块中执行。 - xjcl
在我的情况下,'registerNetworkCallback' 的 onAvailable 方法也适用于 WiFi 的连接和断开。 - Satwinder Singh

15

registerNetworkCallback() 在API 21(Android 5.0,棒棒糖)中添加。它允许您监听满足某些传输类型(WiFi、蜂窝数据、蓝牙等)和能力(SMS、NOT_METERED等)的网络变化。

registerDefaultNetworkCallback() 在API 24(Android 7.0,Nougat)中添加,当任何网络更改发生时使用您的回调,无论传输类型和能力如何。


registerNetworkCallback() 的示例。至少在我的情况下,我不关心过滤器,并希望我的代码适用于任何网络类型。这可以通过空Builder对象实现:

/* Automatically start a download once an internet connection is established */
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
// could filter using .addCapability(int) or .addTransportType(int) on Builder
val networkChangeFilter = NetworkRequest.Builder().build()
cm.registerNetworkCallback(networkChangeFilter, 
    object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) = downloadStuff()
    }
)

上面的代码等同于使用registerDefaultNetworkCallback()的以下代码:


The above code is equivalent to this code with registerDefaultNetworkCallback():
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
cm.registerDefaultNetworkCallback(
    object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) = downloadStuff()
    }
)

令人困惑的 NetworkRequest 实际上只是一种传输类型和功能的过滤器。


默认版本的代码较少,但API级别较低,因此支持的手机较少(74%对94%)。由于我在 ConnectivityManagerCompat 中找不到向后兼容的API调用版本,所以如果21-23个API级别重要,请使用第一个版本。


7
最重要的区别是始终学习。我的答案将是相同的,但我会尝试用不同的方式解释它。
设备可以同时连接到几个网络(例如WiFI和移动网络)。Android选择其中一个已连接的网络作为默认值,因此默认网络用于请求。
区别在于 `registerNetworkCallback` 通知有关所有已连接的网络,而 `registerDefaultNetworkCallback` 则通知有关默认网络。
这就是为什么您无法在 `registerDefaultNetworkCallback` 中传递过滤器的原因 - 过滤一个选择的默认网络没有意义,但对于 `registerNetworkCallback`,它是有意义的,因为可能有许多可用的网络。
您可以在 Android Developer 上找到一个非常好的例子,其中说明了 `registerDefaultNetworkCallback` 和 `registerNetworkCallback` 中您会收到哪些回调。

3
大多数答案都是或多或少正确的。话说,我可以补充的是,在Android中,“默认网络”有特定的含义,因此命名上有所不同。默认网络是指选择为“最佳”设备范围网络的任何网络。该网络将被默认用于任何连接请求。
如果您使用手机并且只有蜂窝连接可用,则该连接将成为默认网络。但是,一旦连接到Wi-Fi,它将成为默认网络,因为它被认为是“最佳”的网络,并且所有未指定任何不同的连接请求现在都将默认使用它,无论他们是否意识到这一点。这是因为只要Wi-Fi具有NetworkCapability.NET_CAPABILITY_NOT_METERED,就认为Wi-Fi比蜂窝更好。现在,如果事实证明Wi-Fi网络实际上是计量网络而蜂窝网络不是,则默认网络将切换回蜂窝网络。
因此,当您使用registerDefaultNetworkCallback()时,实际上是在告诉我有关标记为设备上所有应用程序将默认使用的“最佳”网络发生更改的信息。这就是为什么您不需要作为注册的一部分传递NetworkCapability,因为默认网络由框架控制。 registerNetworkCallback()类似,只是它不关心默认网络。您给它一些NetworkCapability,并跟踪满足这些网络功能的任何网络,无论它们是否是默认网络。
您可以通过查看ConnectivityService中的getDefaultNetwork()来了解更多信息。

1

1
据我所了解,并且除了 @MihaiV 提供的信息之外,它们之间还有另一个区别。ConnectivityManager.registerDefaultNetworkCallback() 是在 API 24 中添加的(如果与 Handler 一起使用,则为 API 26)。而 ConnectivityManager.registerNetworkCallback() 是在 API 21 中添加的(如果与 NetworkRequest 一起使用,则为 API 23)。

registerNetworkCallback 的两个签名都需要一个 NetworkRequest -- 区别在于回调类型 (NetworkCallback vs PendingIntent)。 - xjcl

-1
这里有一个适用于 Android 版本(24 及以上和以下)的解决方案:
class NetworkMonitor(
    private val application: Application,
    val onChange: (isConnected: Boolean) -> Unit
) {
    fun register() {
        (application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).let { connectivityManager ->
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                registerAPI24AndAbove(connectivityManager)
            } else {
                registerAPI24Below(connectivityManager)
            }
        }
    }

    private fun registerAPI24AndAbove(connectivityManager: ConnectivityManager) {
        connectivityManager.registerDefaultNetworkCallback(buildNetworkCallback())
    }

    private fun registerAPI24Below(connectivityManager: ConnectivityManager) {
        NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.TRANSPORT_CELLULAR)
            .addCapability(NetworkCapabilities.TRANSPORT_WIFI)
            .build().let { networkRequest ->
                connectivityManager.registerNetworkCallback(networkRequest, buildNetworkCallback())
            }
    }

    private fun buildNetworkCallback(): ConnectivityManager.NetworkCallback {
        return object : ConnectivityManager.NetworkCallback() {

            override fun onAvailable(network: Network) {
                this@NetworkMonitor.onChange(true)
            }

            override fun onLost(network: Network) {
                this@NetworkMonitor.onChange(false)
            }

        }
    }
}

请确保声明所需的权限!

Manifest.permission.ACCESS_NETWORK_STATE

然后在你的Application类中:

class MyApp : Application() {

    override fun onCreate() {
        super.onCreate()

        NetworkMonitor(this) { isConnected ->
            if (isConnected) {
                // Do your thing
            } else {
                // Do your other thing
            }
        }.register()
    }

}

1
这是一个编程解决方案,但并没有回答问题,即区别。 - CybeX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接