简体   繁体   中英

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

The cellular network isn't lost, but your app isn't allowed to use it. Once WiFi is connected, everything is forced to use that connection. The only exception to this rule is if your phone has a feature called "Dual Acceleration", which allows the cellular connection to stay active (and obviously, the user would have to enable that feature). Alternatively, you may have a setting in your phone's Developer Options called "Cellular Data Always Active", which will do the same thing.

But needless to say, you can't rely on either of those 2 features being enabled in a production environment. So, just assume that when WiFi is connected, that's the only connection that your app can use

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()}")
}    

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM