Make Android simultaneously use WiFi to talk to a device and mobile data to talk to a server?
Asked Answered
J

2

22

I'm developing an Android application which connects to an OBD2 device by Wifi and app can read Speed, RPM, Engine coolant temperature details etc. So wifi is used only for connecting with the OBD2 device(it doesn't have facility to connect with internet, only for communication with local clients). I also need an internet connection for web services. But after connecting my wifi I am not able to connect internet via my mobile data network in android.

The similar application is also developed for iOS. In iOS, I can use device over Wifi (Static Wifi setting) and Internet connection from my cellular network. It means configure my wifi with some static ip I am able to use mobile data network for Internet connection in iOS.

But in Android, If I use static wifi and check for Internet connection, it is not available.

How can I use Wifi and Internet connection both run parallel or any other way by configuring wifi settings in android ?

Jollification answered 26/6, 2014 at 11:21 Comment(4)
this might help #18394566Malang
Part of the problem here is that you have a bad system architecture - the dongle should communicate via something like BLE, ones that do are available.Frumentaceous
@MidasLefko: You would need to look into the multipath stuff added to ConnectivityManager and Network, such as openConnection(). Note that using multiple processes seems to be simpler (e.g., bindProcessToNetwork()), though you seem to prefer to avoid that solution.Acidhead
@CommonsWare, multiProcess is a last resort as the process that connects to the wifi network will need to send many frequent messages to the other process which will necessitate complex IPC implementation.Mb
S
11

Firstly, the problem we may face here is that because there is no internet connection on WiFi network, HTTP data will not go through that connection. See Send request over WiFi (without connection) even if Mobile data is ON (with connection) on Android M for solution

However, I have faced issue where sometimes no HTTP request is successful. To solve this problem, we can use ConnectivityManager.requestNetwork() and Network.openConnection() to achieve this.

Make sure that Mobile data and WiFi network is enabled and Android Manifest has proper connections:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

Variables:

private ConnectivityManager.NetworkCallback mWifiNetworkCallback, mMobileNetworkCallback;
private Network mWifiNetwork, mMobileNetwork;

Get the connectivity manager:

final ConnectivityManager manager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);

Build network callbacks:

if(mWifiNetworkCallback == null){
    //Init only once
    mWifiNetworkCallback = new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(final Network network) {
            try {
                //Save this network for later use
                mWifiNetwork = network;
            } catch (NullPointerException npe) {
                npe.printStackTrace();
            }
        }
    };
}

if(mMobileNetworkCallback == null){
    //Init only once
    mMobileNetworkCallback = new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(final Network network) {
            try {
                //Save this network for later use
                mMobileNetwork = network;
            } catch (NullPointerException npe) {
                npe.printStackTrace();
            }
        }
    };
}

Request networks:

NetworkRequest.Builder wifiBuilder;
wifiBuilder = new NetworkRequest.Builder();
//set the transport type do WIFI
wifiBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
manager.requestNetwork(wifiBuilder.build(), mWifiNetworkCallback);

NetworkRequest.Builder mobileNwBuilder;
mobileNwBuilder = new NetworkRequest.Builder();
//set the transport type do Cellular
mobileNwBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
manager.requestNetwork(mobileNwBuilder.build(), mMobileNetworkCallback);

Make the appropriate request like this:

public void makeHTTPRequest(final String httpUrl, final String payloadJson, final int timeout,
                          final boolean hasHeaders, final String header1, final String header2) {

    try {
        URL url = new URL(httpUrl);
        HttpURLConnection conn = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            conn = (HttpURLConnection) mWifiNetwork.openConnection(url);

            //Or use mMobileNetwork, if and when required
            //conn = (HttpURLConnection) mMobileNetwork.openConnection(url);
        } else {
            conn = (HttpURLConnection) url.openConnection();
        }
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setReadTimeout(timeout * 1000);
        conn.setConnectTimeout(timeout * 1000);

        conn.setDoInput(true);
        conn.setDoOutput(true);

        if(hasHeaders){
            conn.setRequestProperty("header1", header1);
            conn.setRequestProperty("header2", header2);

        }
        conn.setRequestMethod("PUT");

        OutputStream os = conn.getOutputStream();
        os.write(payloadJson.getBytes());
        os.close();

        final int responseCode = conn.getResponseCode();

        if (responseCode == HttpURLConnection.HTTP_OK) {
            final String statusMessage = conn.getResponseMessage();
            //Log this
        } 
    } catch (SocketException se){
        se.printStackTrace();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

Note: These functions are avaialble from Android Lollipop and above. So, it is necessary to use Build.Version.SDK_INT at appropriate place, like this:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
Sundaysundberg answered 3/1, 2019 at 9:30 Comment(0)
C
6
connectivityManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress);

You can request for a certain hostAddress that it must use that type of connectivity. IF you use Hipri then it will take the mobile network. But this can fail ! If it works, then ALL connections to that address will go over that type of connectivity.

You might have to activate it first.

int resultInt = connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");

This can take a couple of seconds, since the hardware modules has to start up.

I've use this on several projects and works great. On old device such as 2.2 it will react really unstable ! But I haven't found any problems on 4.0+

Culbertson answered 22/8, 2014 at 12:48 Comment(3)
can i use wifi socket and mobile network both simultaneously in your solution ?Actuly my requirement is to use both simultaneously...Jollification
Yes you can ! I had the same requirement. Just don't forget to change the routes back. People won't like it if you perhaps change the google analytics routing. That way every call for analytics will go over the data network. After the request is done, The 3g icon next to the wifi will disappear after about 10 seconds.Culbertson
developer.android.com/sdk/api_diff/21/changes/… Both methods are now deprecated...Nougat

© 2022 - 2024 — McMap. All rights reserved.