Search code examples
androidconnectivityandroid-connectivitymanager

Android TRANSPORT_CELLULAR network not available if wifi is connected. How do we make it available?


The moment I get on a wifi connection, the cellular network is completely lost even though the cellular network indicator is definitely on.

This is my network request

val request = NetworkRequest.Builder().run {
    addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
    build()
  }

connectivityManager.registerNetworkCallback(request, callback)

I've tried looking in the connectivityManager.allNetworks list and it's no where to be found. Only the wifi network is in there.

What's even weirder is there is one other cellular network that is always there. It does not have the same ID as my cellular network. There's no connection that can be made with it. It never shows up with registerNetworkCallback. The capabilities on it always include "valid" and "internet"

What am I seeing here? Why is my cellular network lost? What is this phantom cellular network?

  • targetSdkVersion: 29
  • Device: Galaxy S10 - Android 12

Solution

  • I figured this out.

    If you call registerNetworkCallback the above will happen, but if you call requestNetwork with TRANSPORT_CELLULAR,

    connectivityManager.requestNetwork(request, callback)
    

    Android will keep the cellular network around. I was so confused because the documentation was so lacking. Once you do that, it will ask you to add the CHANGE_NETWORK_STATE permission.

    After this step, the network is available, but you won't be able to make any request with it. You have to call

    connectivityManager.bindProcessToNetwork(theCellularNetwork)
    

    to get any connection.

    After this is done, the cellular network can be used in tandem with the wifi network. You can even send some traffic to one and some to the other. If you use OkHttp like I do, you just bind the client with the network's socketFactory

    val client = OkHttpClient().newBuilder().run {
      socketFactory(network.socketFactory)
      build()
    }
    
    client.newCall(
      Request.Builder().url("https://example.com").build()
    ).execute().let {
      Log.i(TAG, "Fetched ${it.body!!.string()}")
    }