如何通过NetworkCallback获取系统弹窗Try Again按钮的点击事件?
解决系统WIFI连接弹窗Try Again点击事件监听问题
核心问题说明
Android系统弹出的WIFI连接重试弹窗(含Try Again/Cancel按钮)属于系统级UI,NetworkCallback无法直接监听该弹窗的按钮点击事件——onUnavailable仅在用户点击Cancel时触发,而Try Again的点击动作由系统内部处理,不会直接回调给APP。
可行解决方案
1. 监听网络扫描结果,间接捕捉重试动作
当用户点击Try Again时,系统会重新扫描附近WIFI热点并尝试连接目标热点。我们可以通过监听WIFI扫描结果,结合连接状态判断用户是否触发了重试:
- 注册
WifiManager.SCAN_RESULTS_AVAILABLE_ACTION广播接收器,监听扫描结果更新 - 在广播回调中检查是否存在目标SSID的热点,若存在且当前处于连接失败状态,则执行自定义重试逻辑
代码示例:
// 注册广播接收器 val wifiReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) { val wifiManager = context?.getSystemService(Context.WIFI_SERVICE) as WifiManager val scanResults = wifiManager.scanResults // 检查是否存在目标热点 val hasTargetSsid = scanResults.any { it.SSID == "AndroidShare_2590" } if (hasTargetSsid) { // 执行自定义重试逻辑,比如重新发起网络请求 reinitiateNetworkConnection() } } } } // 在Activity的onCreate中注册 registerReceiver(wifiReceiver, IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) // 重新发起连接的方法 private fun reinitiateNetworkConnection() { val ssid = "AndroidShare_2590" val password = "adr54adhk523" val wifiNetworkSpecifier = WifiNetworkSpecifier.Builder() .setSsid(ssid) .setWpa2Passphrase(password) .build() val networkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .setNetworkSpecifier(wifiNetworkSpecifier) .build() val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager // 注意先注销之前的callback,避免内存泄漏 connectivityManager.unregisterNetworkCallback(networkCallback) connectivityManager.requestNetwork(networkRequest, networkCallback) }
2. 自定义连接弹窗,完全控制交互逻辑
如果业务允许,可以绕过系统弹窗,自己实现热点检测和连接流程:
- 先扫描WIFI热点,判断目标SSID是否存在
- 若不存在,弹出自定义弹窗(含Try Again/Cancel按钮)
- 点击Try Again时,重新扫描并发起连接;点击Cancel时终止流程
代码示例:
private fun checkAndConnectToHotspot() { val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager val scanResults = wifiManager.scanResults val hasTargetSsid = scanResults.any { it.SSID == "AndroidShare_2590" } if (!hasTargetSsid) { // 弹出自定义弹窗 AlertDialog.Builder(this) .setMessage("无法找到目标热点,是否重试?") .setPositiveButton("Try Again") { _, _ -> // 点击重试时执行自定义逻辑,比如重新扫描+连接 wifiManager.startScan() checkAndConnectToHotspot() } .setNegativeButton("Cancel") { _, _ -> // 取消逻辑 } .show() return } // 目标热点存在,发起连接(即你原有的NetworkCallback逻辑) val ssid = "AndroidShare_2590" val password = "adr54adhk523" val wifiNetworkSpecifier = WifiNetworkSpecifier.Builder() .setSsid(ssid) .setWpa2Passphrase(password) .build() val networkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .setNetworkSpecifier(wifiNetworkSpecifier) .build() val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager connectivityManager.requestNetwork(networkRequest, networkCallback) }
3. 利用NetworkCallback的重试触发逻辑
当用户点击Try Again时,系统会重新发起requestNetwork的流程,此时如果你的NetworkCallback没有被注销,会再次触发连接相关回调。你可以在onUnavailable后不立即注销callback,而是等待系统的重试触发,然后在onAvailable或其他回调中处理:
- 注意:这种方式依赖系统的重试机制,不同版本可能有差异,稳定性不如前两种方案
注意事项
- 权限:需要添加
ACCESS_WIFI_STATE、CHANGE_WIFI_STATE权限,Android 12及以上还需ACCESS_FINE_LOCATION权限才能获取扫描结果 - 内存泄漏:注册广播或NetworkCallback后,在Activity销毁时务必注销,避免内存泄漏
内容的提问来源于stack exchange,提问作者Hardik Parmar
相关产品推荐
相关产品推荐

