2

I'm trying to get my app to connect to a WiFi AP to provide Internet with WifiNetworkSpecifier using code like this. But it's always calling onUnavailable in the NetworkCallback.

private val callback: ConnectivityManager.NetworkCallback = object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network: Network) {
        super.onAvailable(network)
    }
    override fun onLost(network: Network) {
        super.onLost(network)
    }
    override fun onLosing(network: Network, maxMsToLive: Int) {
        super.onLosing(network, maxMsToLive)
    }
    override fun onUnavailable() {
        super.onUnavailable()
    }
    override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
        super.onCapabilitiesChanged(network, networkCapabilities)
    }
    override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) {
        super.onLinkPropertiesChanged(network, linkProperties)
    }
    override fun onBlockedStatusChanged(network: Network, blocked: Boolean) {
        super.onBlockedStatusChanged(network, blocked)
    }
}

val networkSpecifier: NetworkSpecifier = WifiNetworkSpecifier.Builder()
        .setSsid("SsidName")
        .setWpa2Passphrase("wifipassword")
        .build()

    val networkRequest: NetworkRequest = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .setNetworkSpecifier(networkSpecifier)
        .build()
    connectivityManager.requestNetwork(networkRequest, callback, 100000)
georgiecasey
  • 21,793
  • 11
  • 65
  • 74

1 Answers1

3

The WifiNetworkSpecifier is only meant to connect to local-only Wifi networks, for example, to set up IoT devices, as confirmed here: https://developer.android.com/guide/topics/connectivity/wifi-bootstrap

enter image description here

So if you .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET), Android will always just do nothing and call onUnavailable.

You can see why in the Android platform code here: https://cs.android.com/android/platform/superproject/+/master:packages/modules/Wifi/service/java/com/android/server/wifi/WifiNetworkFactory.java;drc=08124f52b883c61f3e17bc57dc28eca4c7f7bb72;l=487

The message in your LogCat will be E/WifiNetworkFactory: Request with wifi network specifier cannot contain NET_CAPABILITY_INTERNET. Rejecting

If you want Internet, you need to remove the .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) line (which makes a lot of sense, wha!) and add connectivityManager.bindProcessToNetwork(network) in onAvailable as described over in this answer. Note this is a bit of a hack and will enable Internet via Wifi for your app only.

georgiecasey
  • 21,793
  • 11
  • 65
  • 74
  • Thanks for the information! I didn’t know it! What happen if we want to connect to a wifi network from an app like we do it in the settings? Is there any way to do it in Android? Thanks in advance!! – daaanigm Jan 12 '23 at 23:21
  • @daaanigm in the latest Android versions, no. For our use case, we even had our Android devices rooted and I couldn't find a way to do it like you would manually by going to settings and having it work for all apps on the phone. If you figure out a way, report back! – georgiecasey Jan 12 '23 at 23:34
  • I think if you use the class NetworkSuggestion we can do it, I need to try this class, but it will send a local notification to the user to connect to a specific wifi and I think this connection is a system level. Let me know if you try it before than me. Thanks! – daaanigm Jan 14 '23 at 12:30
  • @daaanigm ah yes that works, but we wanted to do it without any user interaction – georgiecasey Jan 14 '23 at 13:14