20

我正在开发一个通过 Wifi 连接到 OBD2 设备的 Android 应用程序,并且应用程序可以读取速度、RPM、发动机冷却液温度详细信息等。所以 wifi 仅用于连接 OBD2 设备(它没有连接的设施)互联网,仅用于与本地客户通信)。我还需要网络服务的互联网连接。但是在连接我的 wifi 后,我无法通过我在 android 中的移动数据网络连接互联网。

类似的应用程序也是为 iOS 开发的。在 iOS 中,我可以通过 Wifi(静态 Wifi 设置)和蜂窝网络的 Internet 连接使用设备。这意味着使用一些静态 IP 配置我的 wifi,我可以在 iOS 中使用移动数据网络进行 Internet 连接。

但在 Android 中,如果我使用静态 wifi 并检查 Internet 连接,则它不可用。

如何通过在 android 中配置 wifi 设置来使用 Wifi 和 Internet 连接并行运行或以任何其他方式运行?

4

2 回答 2

10

首先,我们在这里可能面临的问题是,由于 WiFi 网络上没有 Internet 连接,HTTP 数据不会通过该连接。即使移动数据在 Android M 上打开(有连接),请参阅通过 WiFi(无连接)发送请求以获取解决方案

但是,我遇到了有时没有 HTTP 请求成功的问题。为了解决这个问题,我们可以使用ConnectivityManager.requestNetwork()Network.openConnection()来实现。

确保已启用移动数据和 WiFi 网络并且 Android Manifest 具有正确的连接:

<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" />

变量:

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

获取连接管理器:

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

构建网络回调:

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

请求网络:

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);

像这样提出适当的请求:

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

注意: 这些功能在 Android Lollipop 及以上版本中可用。所以,有必要Build.Version.SDK_INT在适当的地方使用,像这样:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
于 2019-01-03T09:30:44.487 回答
6
connectivityManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress);

您可以请求某个主机地址,它必须使用该类型的连接。如果您使用 Hipri,那么它将占用移动网络。但这可能会失败!如果它有效,那么到该地址的所有连接都将通过该类型的连接。

您可能必须先激活它。

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

这可能需要几秒钟,因为硬件模块必须启动。

我已经在几个项目中使用它并且效果很好。在 2.2 等旧设备上,它的反应真的很不稳定!但是我在4.0+上没有发现任何问题

于 2014-08-22T12:48:49.620 回答