我在 Android 11 中测试了这段代码
val networkRequest = NetworkRequest.Builder().apply {
addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
}.build()
connectivityManager.registerNetworkCallback(networkRequest, object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
val wifiName = getCurrentlyConnectedName() ?: return
val wifiMac = getCurrentlyConnectedMac() ?: return
Timber.d("WifiStateManager onAvailable() called with: network = [$wifiName]")
}
override fun onLost(network: Network) {
super.onLost(network)
Timber.d("WifiStateManager onLost() called with: network = [$network]")
}
})
并注意到一种奇怪的行为。当应用程序在后台时,
wifi ssid
始终为<unknown>
(请注意,位置权限被授予100%)。当应用程序位于前台时,一切正常,我得到正确的wifi ssid
。
为什么会发生这种情况? Android 11 上应用程序处于后台时如何获取 wifi SSID?
奇怪的是,这个问题没有早点得到答复。
位置权限现在在 Android 11+ 上有一个后台访问的特殊情况。一个应用程序可以被授予访问位置的权限,但只能在前台运行。后台位置权限需要在 Play Console 上提出特殊请求才能发布并获得相应的权限:
android.permission.ACCESS_BACKGROUND_LOCATION
从定位 API 29 开始,我相信这在 Play 商店中已经是强制性的。
这是 Android 10+(API 29 及更高版本) 上的正确行为,声明
ACCESS_COARSE_LOCATION
或 ACCESS_FINE_LOCATION
权限是不够的。
1。对于前景位置:
您还需要在服务中声明
foregroundServiceType
或 location
才能使用前台位置。
<service
android:name="MyNavigationService"
android:foregroundServiceType="location" ... >
<!-- Any inner elements would go here. -->
</service>
或者,如果您的代码在 Activity 中运行,则该 Activity 应该对用户可见。
2。对于背景位置:
正如 3c71 所说,您应该在应用程序的清单中声明
ACCESS_BACKGROUND_LOCATION
权限,以便在运行时请求后台位置访问。
由于 Google Play 位置政策,它可能会拒绝需要后台位置权限的应用程序。所以,我认为前景位置应该是更好的选择。
官方文档:https://developer.android.com/training/location/permissions
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" /> <uses-permission android:name="android.permission.NEARBY_DEVICES" />
https://developer.android.com/about/versions/13/behavior-changes-13#nearby-wifi-devices-permission