6

I noticed that while streaming audio from a remote server through 3G (mobile) connection and while the WIFI is disconnected or OFF, as soon as WIFI is activated and connected, connection through 3G is dropped.

I want the app keep using 3G even if WIFI is connected too now. I want to do this to keep continuity. (User may opt-in/out to/from this behaviour).

Is there a special flag, lock, etc.. For this purpose?

frankish
  • 6,738
  • 9
  • 49
  • 100

1 Answers1

18

This isn't possible on devices before Android 5.0 (Lollipop). The OS only keeps one interface up at a time, and applications don't have any control over this choice.

On devices running Android 5.0 or newer, you can use the new multi-networking APIs to pick which interface you want to use for network traffic.

Here's the steps to do this, from the Android 5.0 changelog:

To select and connect to a network dynamically from your app, follow these steps:

  1. Create a ConnectivityManager.
  2. Use the NetworkRequest.Builder class to create an NetworkRequest object and specify the network features and transport type your app is interested in.
  3. To scan for suitable networks, call requestNetwork() or registerNetworkCallback(), and pass in the NetworkRequest object and an implementation of ConnectivityManager.NetworkCallback. Use the requestNetwork() method if you want to actively switch to a suitable network once it’s detected; to receive only notifications for scanned networks without actively switching, use the registerNetworkCallback() method instead.

When the system detects a suitable network, it connects to the network and invokes the onAvailable() callback. You can use the Network object from the callback to get additional information about the network, or to direct traffic to use the selected network.

Specifically, if you want to force your traffic over 3G/LTE, even if there's a WiFi signal present, you'd use something like this:

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
                          Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder req = new NetworkRequest.Builder();
req.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
cm.requestNetwork(req.build(), new ConnectivityManager.NetworkCallback() {

    @Override
    public void onAvailable(Network network) {
        // If you want to use a raw socket...
        network.bindSocket(...);
        // Or if you want a managed URL connection...
        URLConnection conn = network.openConnection(...);
    }

    // Be sure to override other options in NetworkCallback() too...

}
Trevor Johns
  • 15,682
  • 3
  • 55
  • 54
  • Great information! Thank you very much! Do you have an idea on how to lock in to 3G by the NDK side? (Staying connected to 3G in c/c++ side, as I connect to server with NDK) – frankish Apr 24 '15 at 05:35
  • 1
    This API is only available in Android's Java framework, so if you want to access it from within the NDK you'd have to use JNI to make a call from C++ into Java. – Trevor Johns Apr 24 '15 at 07:29
  • 1
    Hi @TrevorJohns, if I use this method to send Http requests during the "onAvailable", will they be send from the specified network? For example, I'm using AsyncHttpClient for that. If I call client.Get() within the onAvailable, will that request be routed through the specified network? – Konstantinos Jan 06 '16 at 13:51
  • Perfect solution,Binding to cellular is done now If i wanted to unbind from cellular what could be the way. It's urgent for me. – Guruprasad Jan 22 '18 at 10:05
  • To unbind from the requested network call connectionManager.unregisterNetworkCallback(callback); – Isham Oct 10 '18 at 11:05