Luj*_*a93 5 android internet-connection android-networking android-wifi android-10.0
我正在构建一个应用程序,其中与第二个设备的连接是本质。因此,我使用了WifiNetworkSpecifier API。但是,一旦用户离开并返回 Wi-Fi 边界,应用程序必须能够自动重新连接到目标网络。因此,我使用了WifiNetworkSuggestion API。但是,我在那里遇到了几个问题:
到目前为止,根据我的经验和理解(这可能是错误的),似乎我们必须手动取消注册先前分配给说明符请求的网络回调,或者终止应用程序,然后让建议 API 完成它的工作,直到它可以工作适当地。如果边界中存在其他网络(用户之前使用 OS Wi-Fi 管理器连接到该网络),这可能会出现问题。在这种情况下,我们永远不会自动重新连接到应用程序定义的 SSID,建议 API 也永远不会工作。
问题是:如何将这两个 API 结合起来,以便能够连接到 SSID,但又可以自动重新连接,而不会进行手动断开用户连接或杀死应用程序等丑陋的黑客攻击,这也不能给我们任何保证?
在我看来,这个使用新网络 API 的全新实现做得不好,它给开发人员带来了很多问题和限制,或者至少它的文档很差。
这是用于发出请求的代码。请注意,我连接的设备没有实际的互联网访问权限,它只是用作 p2p 网络。
@RequiresApi(api = Build.VERSION_CODES.Q)
private fun connectToWiFiOnQ(wifiCredentials: WifiCredentials, onUnavailable: () -> Unit) {
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.setNetworkSpecifier(createWifiNetworkSpecifier(wifiCredentials))
.build()
networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
connectivityManager.bindProcessToNetwork(network)
}
override fun onUnavailable() {
super.onUnavailable()
onUnavailable.invoke()
}
}
networkCallback?.let {
addNetworkSuggestion(wifiCredentials)
connectivityManager.requestNetwork(request, it)
}
}
@RequiresApi(api = Build.VERSION_CODES.Q)
private fun addNetworkSuggestion(wifiCredentials: WifiCredentials) {
wifiManager.addNetworkSuggestions(listOf(createWifiNetworkSuggestion(wifiCredentials))).apply {
if (this != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
if (this == WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP) {
wifiManager.removeNetworkSuggestions(emptyList())
addNetworkSuggestion(wifiCredentials)
}
}
}
suggestionBroadcastReceiver?.let { context.unregisterReceiver(it) }
suggestionBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action != WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)
return
// Post connection processing..
}
}
context.registerReceiver(
suggestionBroadcastReceiver, IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)
)
}
@RequiresApi(api = Build.VERSION_CODES.Q)
private fun createWifiNetworkSpecifier(wifiCredentials: WifiCredentials): WifiNetworkSpecifier {
return when (wifiCredentials.authenticationType.toLowerCase()) {
WifiCipherType.NOPASS.name.toLowerCase() -> WifiNetworkSpecifier.Builder()
.setSsid(wifiCredentials.networkSSID)
.setIsHiddenSsid(wifiCredentials.isSSIDHidden)
.build()
WifiCipherType.WPA.name.toLowerCase() -> WifiNetworkSpecifier.Builder()
.setSsid(wifiCredentials.networkSSID)
.setWpa2Passphrase(wifiCredentials.password)
.setIsHiddenSsid(wifiCredentials.isSSIDHidden)
.build()
else -> WifiNetworkSpecifier.Builder()
.setSsid(wifiCredentials.networkSSID)
.setIsHiddenSsid(wifiCredentials.isSSIDHidden)
.build()
}
}
@RequiresApi(api = Build.VERSION_CODES.Q)
private fun createWifiNetworkSuggestion(wifiCredentials: WifiCredentials): WifiNetworkSuggestion {
return when (wifiCredentials.authenticationType.toLowerCase()) {
WifiCipherType.NOPASS.name.toLowerCase() -> WifiNetworkSuggestion.Builder()
.setSsid(wifiCredentials.networkSSID)
.setIsHiddenSsid(wifiCredentials.isSSIDHidden)
.build()
WifiCipherType.WPA.name.toLowerCase() -> WifiNetworkSuggestion.Builder()
.setSsid(wifiCredentials.networkSSID)
.setWpa2Passphrase(wifiCredentials.password)
.setIsHiddenSsid(wifiCredentials.isSSIDHidden)
.build()
else -> WifiNetworkSuggestion.Builder()
.setSsid(wifiCredentials.networkSSID)
.setIsHiddenSsid(wifiCredentials.isSSIDHidden)
.build()
}
}
Run Code Online (Sandbox Code Playgroud)
调用建议 APIonAvailable对我有用。这样用户就不会同时看到两个弹出窗口。
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
connectivityManager.bindProcessToNetwork(network)
addNetworkSuggestion(wifiCredentials)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
768 次 |
| 最近记录: |