23
votes

I am developing a mobile application (iOS and Android) to control a device over Wi-Fi. The device creates a wireless network (SoftAP) but does not provide access to the internet.

On iOS, I can connect to the device and make requests to its IP address (192.168.70.1) but all other requests fall back to the mobile network. This allows the phone to maintain internet connectivity while connected to the device over Wi-Fi.

On Android, if I connect to the device wireless network, internet requests do not fall back to the mobile connection, they just fail.

In my Android app, I can use ConnectivityManager.requestRouteToHost to force requests from my app to use the mobile network. However, requests made by other apps still use the device wifi network and fail.

I have also tried to use the ConnectivityManager to change the network preference with :

ConnectivityManager.setNetworkPreference(ConnectivityManager.TYPE_MOBILE)

This causes the phone to use the mobile network for all requests from all applications. Wi-Fi is disabled. It seems that in previous versions of Android Wi-Fi could still be used even if it is not the "preferred" network but this does not seem to work in KitKat. It is possibly related to a change in Android 4.2: https://code.google.com/p/android/issues/detail?id=73509 "ConnectivityManager since 4.2 tears down networks that are not the NetworkPreference"

Is there a solution that allows an Android app to use Wi-Fi for a specific IP address and the mobile network for everything else? Maybe this can be done via the NDK?

4
Did you find a solution to specify witch network you want to use on all android versions ?DjimOnDev
No. It may be there is a solution for Lollipop but I have not had time to investigate it yet.Paul Greyson
@PaulGreyson, how did you do this for iOS? I am looking for a similar solution to make http requests over the mobile network while the device is on wifi.keno
on iOS it "just works" so long as the wifi router doesn't say it can route internet requests. In my case, the logic was all in udhcpd.conf on the device providing the AP where I did not provide the option subnet, domain and dns settings. iOS apparently recognizes that this means the AP is not a proper gateway and goes to LTE.Paul Greyson

4 Answers

10
votes

Actually you can, but only since Lollipop (API 21).

From the Android API 21 Documentation:

    Android 5.0 provides new multi-networking APIs that let your app dynamically scan for available
networks with specific capabilities, and establish a connection to them. This functionality is useful
when your app requires a specialized network, such as an SUPL, MMS, or carrier-billing network, or if
you want to send data using a particular type of transport protocol.

So you can use the NetworkRequest.Builder class to create a NetworkRequest that sends the request over a certain Transport Type.

Use the following function:

NetworkRequest.Builder addTransportType(int transportType)

To set transport types (WIFI, ETHERNET or CELLULAR for example) for your requests.

3
votes

Android normally tears down the networks that are not network preference. A work-around you could use is create an AP through the mobile app and let the device connect to it. This way the mobile can maintain internet connectivity as well as communicate with the device.

Refer the following links for implementation details:

https://github.com/opengarden/android-tether

https://code.google.com/p/android-wifi-tether/

2
votes

Similar Asked before as Enable simultaneously wifi and 3G interface on Android and quick answer was NO.

But it is actually possible and implemented in some software like SuperDownload ( see stackexchange )

That software require root.


(source: geeknizer.com)

Two channel download also is advertized in some new Android phone. (I cannot find link, they used new marketing term for WiFi+3G used together)

Is there a solution that allows an Android app to use Wi-Fi for a specific IP address and the mobile network for everything else? Maybe this can be done via the NDK?

Possibly because WiFi is needed only for local address, you could go way of making special WiFi driver, but that again, would not be simple.

And going further down into software:

this feature is TCP/IP packages routing. If you know how to implement so on Linux, you are half done. The next would be getting it work on Android. But I guess it would not be enable for non-system app, as this would be easy exploitable security whole (e.g. substitute bank server IP )

1
votes

This might be a simple solution: set WiFi as preferred interface each time you need to control the device, and set mobile network preferred right after finishing the job. Doing this might interrupt concurrent Internet activities, but remind that TCP and most apps allow delay up to a few seconds (or even more). The interruption is negligible if the controlling job for your device is sporadic and never requires long-time waiting.

If the above situation is not the case, do the reverse: set WiFi as preferred interface as default, and set mobile network preferred whenever you don't have to control the device. But make sure you switch back to mobile network frequently, say every 3 seconds, to prevent timeout of your Internet activities.