Android API29+编程连接Wi-Fi:实现应用外网络可用方案
如何让通过WifiNetworkSpecifier连接的Wi-Fi在应用外生效
当前我使用WifiNetworkSpecifier.Builder连接指定SSID的Wi-Fi,但网络仅在当前应用内可用。请问如何实现连接后该Wi-Fi能在应用外正常使用?
以下是我当前的代码(可连接SSID但仅应用内有网络):
WifiNetworkSpecifier specifier = new WifiNetworkSpecifier.Builder() .setSsid("ssid") .setWpa2Passphrase("password") .build(); NetworkRequest request = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .setNetworkSpecifier(specifier) .build(); ConnectivityManager connectivityManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE); ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() { public void onAvailable(Network network) { connectivityManager.bindProcessToNetwork(network); Log.e(TAG,"Connected to password-protected Wi-Fi network"); ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); cm.bindProcessToNetwork(network); NetworkCapabilities capabilities = cm.getNetworkCapabilities(network); if (capabilities != null) { if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); currentConnectedSSID = wifiInfo.getSSID(); } } } @Override public void onUnavailable() { // do failure processing here.. Log.e(TAG,"Failed to connect to password-protected Wi-Fi network"); } }; connectivityManager.requestNetwork(request, networkCallback);
原因分析
你当前的实现是应用私有网络连接:
WifiNetworkSpecifier搭配requestNetwork创建的是应用绑定的网络,默认仅当前应用进程可使用bindProcessToNetwork进一步将当前进程绑定到该网络,强化了应用独占的特性- 代码中还移除了
NET_CAPABILITY_INTERNET能力,导致系统不会将该网络作为全局互联网连接
解决方案:实现系统级Wi-Fi连接
要让Wi-Fi在应用外生效,需要创建系统级的Wi-Fi连接,而非应用私有连接,推荐两种方式:
方式1:Android 10+ 使用WifiNetworkSuggestion(推荐)
Android 10及以上推荐使用WifiNetworkSuggestion向系统建议连接Wi-Fi,系统会处理全局连接:
// 构建Wi-Fi建议 List<WifiNetworkSuggestion> suggestions = new ArrayList<>(); WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() .setSsid("ssid") .setWpa2Passphrase("password") .build(); suggestions.add(suggestion); // 获取WifiManager WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); // 提交建议并监听结果 int status = wifiManager.addNetworkSuggestions(suggestions); if (status == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) { // 建议提交成功,系统会自动尝试连接 // 可注册广播监听连接状态:WifiManager.NETWORK_STATE_CHANGED_ACTION } else { // 提交失败,处理错误 } // 权限要求:需要在Manifest中添加 // <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> // <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> // Android 13+ 还需要 android.permission.NEARBY_WIFI_DEVICES
方式2:传统WifiManager方式(兼容Android 9及以下)
对于低版本系统,可使用传统的WifiManager API添加并启用网络:
// 构建Wi-Fi配置 WifiConfiguration config = new WifiConfiguration(); config.SSID = "\"ssid\""; // 注意SSID需要加引号 config.preSharedKey = "\"password\""; // WPA2密码也需要加引号 config.status = WifiConfiguration.Status.ENABLED; config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); // 获取WifiManager WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); // 添加网络并获取网络ID int networkId = wifiManager.addNetwork(config); if (networkId != -1) { // 启用该网络 boolean isEnabled = wifiManager.enableNetwork(networkId, true); if (isEnabled) { Log.e(TAG, "Wi-Fi已全局启用"); } else { Log.e(TAG, "启用Wi-Fi失败"); } } else { Log.e(TAG, "添加Wi-Fi配置失败"); } // 权限要求:Manifest中添加 // <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> // <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
注意事项
- 无论哪种方式,都需要申请对应的Wi-Fi权限,部分版本还需要位置权限
- 系统级连接会受系统Wi-Fi策略影响(比如已保存的优先级更高的网络)
- 若目标Wi-Fi需要互联网访问,不要移除
NET_CAPABILITY_INTERNET能力
内容的提问来源于stack exchange,提问作者theMountainMan
相关产品推荐
相关产品推荐

