力的Andr​​oid使用3G的时候就没有网络接入局域无线上网 [英] Force Android to use 3G when on local area wifi without net access

查看:418
本文介绍了力的Andr​​oid使用3G的时候就没有网络接入局域无线上网的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个无线LAN设置不具备互联网连接。连接到它只是其他各种本地的无线网络设备。该DHCP配置为不返回网关或DNS服务器。只有一个IP地址和子网掩码。

当我我的Andr​​oid连接到该无线AP它连接正常,但手机上的所有互联网连接停止工作。

我预计,由于无线网络没有网关设置,机器人要实现互联网无法通过该连接,而应该通过3G连接,这在5条进行路由。

我试过在android手机设置静态IP为好,但这并没有帮助。

的主要原因设置是为了让Android设备可以在此远程网络上的数据传输到一个基于互联网的服务器,因为它可以连接到本地设备没有问题。然而,3G侧被打破,一旦WiFi是设置。

在如何解决这个问题有什么想法?

解决方案

在进行位编码和测试我已合并Squonk和解决方案。这是我创建的类:

 包it.helian.exampleprj.network;

进口的java.net.InetAddress;
进口的java.net.UnknownHostException;

进口android.content.Context;
进口android.net.ConnectivityManager;
进口android.net.NetworkInfo.State;
进口android.net.wifi.WifiManager;
进口android.text.TextUtils;
进口android.util.Log;

公共类NetworkUtils {
    私有静态最后弦乐TAG_LOG =ExamplePrj;

    上下文语境;
    WifiManager wifiMan = NULL;
    WifiManager.WifiLock wifiLock = NULL;

    公共NetworkUtils(上下文的背景下){
        超();
        this.context =背景;
    }

    / **
     *启用特定地址的移动连接
     *参数上下文语境(应用程序或活动)
     *参数地址的地址,以使
     * @返回如此成功,否则为假
     * /
    公共布尔forceMobileConnectionForAddress(上下文的背景下,字符串地址){
        ConnectivityManager connectivityManager =(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
        如果(空== connectivityManager){
            Log.d(TAG_LOG,ConnectivityManager为空,也不能试图迫使移动连接);
            返回false;
        }

        //检查移动连接可用,并且连接
        状态状态= connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
        Log.d(TAG_LOG,TYPE_MOBILE_HIPRI网络状态:+状态);
        如果(0 == state.compareTo(State.CONNECTED)|| 0 == state.compareTo(State.CONNECTING)){
            返回true;
        }

        //激活除了已经激活的其他连接移动连接
        INT resultInt = connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILEenableHIPRI);
        Log.d(TAG_LOG,startUsingNetworkFeature为enableHIPRI结果:+ resultInt);

        //  -  1表示错误
        // 0表示已启用
        // 1表示启用
        //其他值可以退换,因为这种方法是特定于供应商
        如果(-1 == resultInt){
            Log.e(TAG_LOG,startUsingNetworkFeature,也许问题的错误结果);
            返回false;
        }
        如果(0 == resultInt){
            Log.d(TAG_LOG,无需执行其他网络设置);
            返回true;
        }

        //找到主机名路由
        字符串主机= extractAddressFromUrl(地址);
        Log.d(TAG_LOG,源地址+地址);
        Log.d(TAG_LOG,目标主机地址路由:+主机名);
        如果(TextUtils.isEmpty(主机名))主机名=地址;

        //创建一个指定地址的路由
        INT hostAddress = lookupHost(主机名);
        如果(-1 == hostAddress){
            Log.e(TAG_LOG,错误的主机地址转换,结果是-1);
            返回false;
        }
        //等待需要连接管理器醒来一段时间
        尝试 {
            为(中间体计数器= 0;计数器小于30;计数器++){
                状态的CheckState = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
                如果(0 == checkState.compareTo(State.CONNECTED))
                    打破;
                视频下载(1000);
            }
        }赶上(InterruptedException异常E){
            //没事做
        }
        布尔resultBool = connectivityManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI,hostAddress);
        Log.d(TAG_LOG,requestRouteToHost结果:+ resultBool);
        如果(!resultBool)
            Log.e(TAG_LOG,错requestRouteToHost结果:预期的事实,但是是假的);

        状态= connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
        Log.d(TAG_LOG,经过路由TYPE_MOBILE_HIPRI网络状态:+状态);

        返回resultBool;
    }

    / **
     *从地址的主机名此方法提取
     *参数的URL如。 http://some.where.com:8080/sync
     * @返回some.where.com
     * /
    公共字符串extractAddressFromUrl(字符串URL){
        字符串urlToProcess = NULL;

        //发现协议
        INT protocolEndIndex = url.indexOf(://);
        如果(protocolEndIndex大于0){
            urlToProcess = url.substring(protocolEndIndex + 3);
        } 其他 {
            urlToProcess =网址;
        }

        //如果我们在地址端口号,我们剥夺一切
        //端口号后,
        INT POS = urlToProcess.indexOf(:);
        如果(POS> = 0){
            urlToProcess = urlToProcess.substring(0,POS);
        }

        //如果我们有资源位置的地址,然后我们剥去
        //一切后'/'
        POS = urlToProcess.indexOf('/');
        如果(POS> = 0){
            urlToProcess = urlToProcess.substring(0,POS);
        }

        //如果我们有吗?在地址那么我们剥去
        //之后的所有?
        POS = urlToProcess.indexOf(?);
        如果(POS> = 0){
            urlToProcess = urlToProcess.substring(0,POS);
        }
        返回urlToProcess;
    }

    / **
     *在使用int值变换主机名{@link ConnectivityManager.requestRouteToHost}
     * 方法
     *
     * @参数主机名
     * @返回-1,如果主机不存在,在其他地方的翻译
     *为整数
     * /
    私人诠释lookupHost(字符串主机名){
        InetAddress类InetAddress类;
        尝试 {
            InetAddress类= InetAddress.getByName(主机名);
        }赶上(UnknownHostException异常E){
            返回-1;
        }
        byte []的addrBytes;
        INT地址;
        addrBytes = inetAddress.getAddress();
        ADDR =((addrBytes [3]&安培; 0xff的)所述;&所述; 24)
                | ((addrBytes [2]&安培; 0xff的)所述;&所述; 16)
                | ((addrBytes [1]&安培; 0xff的)所述;&所述; 8)
                | (addrBytes [0]&安培; 0xff的);
        返回地址;
    }

    @燮pressWarnings(未使用)
    私人诠释lookupHost2(字符串主机名){
        InetAddress类InetAddress类;
        尝试 {
            InetAddress类= InetAddress.getByName(主机名);
        }赶上(UnknownHostException异常E){
            返回-1;
        }
        byte []的addrBytes;
        INT地址;
        addrBytes = inetAddress.getAddress();
        ADDR =((addrBytes [3]&安培; 0xff的)所述;&所述; 24)


        | ((addrBytes [2]&安培; 0xff的)所述;&所述; 16)
            | ((addrBytes [1]&安培; 0xff的)所述;&所述; 8)
            | (addrBytes [0]&安培; 0xff的);
        返回地址;
    }

    公布尔disableWifi(){
        wifiMan =(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
        如果(wifiMan!= NULL){
            wifiLock = wifiMan.createWifiLock(WifiManager.WIFI_MODE_SCAN_ONLYHelianRCAWifiLock);
        }
        返回wifiMan.setWifiEnabled(假);
    }

    公布尔enableWifi(){
        布尔成功= FALSE;

        如果(wifiLock = NULL和放大器;!&安培; wifiLock.isHeld())
            wifiLock.release();
        如果(wifiMan!= NULL)
        成功= wifiMan.setWifiEnabled(真正的);
        返回成功;
    }
}
 

这是在使用

的用法code

 布尔mobileRoutingEnabled = checkMobileInternetRouting();

            如果(!mobileRoutingEnabled){
                networkUtils.disableWifi();

                尝试 {
                    视频下载(3000);
                }赶上(InterruptedException异常E){
                    // TODO自动生成的catch块
                    e.printStackTrace();
                }
            }

            networkUtils.forceMobileConnectionForAddress(背景下,RCA_URL);

            如果(!mobileRoutingEnabled){
                networkUtils.enableWifi();
            }

            //本次检查是用于测试目的
            checkMobileInternetRouting();

            返回callWebService(RCA_COMPLETE_URL,_plate);
 

其中 checkMobileInternetRouting 是:

 私人布尔checkMobileInternetRouting(){
    ConnectivityManager厘米=(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

    状态状态= cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
    返回0 == state.compareTo(State.CONNECTED)|| 0 == state.compareTo(State.CONNECTING);
}
 

使用步骤

  1. 检查路由到主机启​​用
  2. 如果是去与无论是无线连接的通信或没有,只执行6点(点4只检查路由已启用,不执行任何rilevant动作)。否则,临时禁用无线网络。
  3. 为让3G连接约3秒线程睡眠回来
  4. 设置各3g路由到特定网址
  5. 启用回无线
  6. 现在,给定的URL,可即使没有网络存取权限WiFi连接名为

结论

这是一个有点哈克,但工作正常。唯一的问题是,这个路由已经得到了几秒钟的延时(如20-30),迫使你执行上述步骤一次整。设置此超时到一个更高的价值将是非常不错的。

I have a wifi LAN setup which does not have internet access. Just various other local wifi devices connected to it. The DHCP is configured to not return a gateway or dns server. Only an IP and netmask.

When I connect my android to this wifi AP it connects fine, but all internet connectivity on the phone stops working.

I would expect that since the wifi has no gateway setting that android should realize the internet can't go through that connection and should instead be routed through the 3G connection which is at 5 bars.

I've tried setting a static IP on the android phone as well, but this did not help.

The main reason for this setup is so that the android device can transfer data on this remote network to an internet based server since it can connect to the local devices without issue. However the 3G side is broken once the wifi is setup.

Any thoughts on how to work around this issue?

解决方案

After a bit of coding and testing I have merged Squonk and this solution. This is the class I have created:

package it.helian.exampleprj.network;

import java.net.InetAddress;
import java.net.UnknownHostException;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo.State;
import android.net.wifi.WifiManager;
import android.text.TextUtils;
import android.util.Log;

public class NetworkUtils {
    private static final String TAG_LOG = "ExamplePrj";

    Context context;
    WifiManager wifiMan = null;
    WifiManager.WifiLock wifiLock = null;

    public NetworkUtils(Context context) {
        super();
        this.context = context;
    }

    /**
     * Enable mobile connection for a specific address
     * @param context a Context (application or activity)
     * @param address the address to enable
     * @return true for success, else false
     */
    public boolean forceMobileConnectionForAddress(Context context, String address) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (null == connectivityManager) {
            Log.d(TAG_LOG, "ConnectivityManager is null, cannot try to force a mobile connection");
            return false;
        }

        //check if mobile connection is available and connected
        State state = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
        Log.d(TAG_LOG, "TYPE_MOBILE_HIPRI network state: " + state);
        if (0 == state.compareTo(State.CONNECTED) || 0 == state.compareTo(State.CONNECTING)) {
            return true;
        }

        //activate mobile connection in addition to other connection already activated
        int resultInt = connectivityManager.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI");
        Log.d(TAG_LOG, "startUsingNetworkFeature for enableHIPRI result: " + resultInt);

        //-1 means errors
        // 0 means already enabled
        // 1 means enabled
        // other values can be returned, because this method is vendor specific
        if (-1 == resultInt) {
            Log.e(TAG_LOG, "Wrong result of startUsingNetworkFeature, maybe problems");
            return false;
        }
        if (0 == resultInt) {
            Log.d(TAG_LOG, "No need to perform additional network settings");
            return true;
        }

        //find the host name to route
        String hostName = extractAddressFromUrl(address);
        Log.d(TAG_LOG, "Source address: " + address);
        Log.d(TAG_LOG, "Destination host address to route: " + hostName);
        if (TextUtils.isEmpty(hostName)) hostName = address;

        //create a route for the specified address
        int hostAddress = lookupHost(hostName);
        if (-1 == hostAddress) {
            Log.e(TAG_LOG, "Wrong host address transformation, result was -1");
            return false;
        }
        //wait some time needed to connection manager for waking up
        try {
            for (int counter=0; counter<30; counter++) {
                State checkState = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
                if (0 == checkState.compareTo(State.CONNECTED))
                    break;
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            //nothing to do
        }
        boolean resultBool = connectivityManager.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress);
        Log.d(TAG_LOG, "requestRouteToHost result: " + resultBool);
        if (!resultBool)
            Log.e(TAG_LOG, "Wrong requestRouteToHost result: expected true, but was false");

        state = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
        Log.d(TAG_LOG, "TYPE_MOBILE_HIPRI network state after routing: " + state);

        return resultBool;
    }

    /**
     * This method extracts from address the hostname
     * @param url eg. http://some.where.com:8080/sync
     * @return some.where.com
     */
    public String extractAddressFromUrl(String url) {
        String urlToProcess = null;

        //find protocol
        int protocolEndIndex = url.indexOf("://");
        if(protocolEndIndex>0) {
            urlToProcess = url.substring(protocolEndIndex + 3);
        } else {
            urlToProcess = url;
        }

        // If we have port number in the address we strip everything
        // after the port number
        int pos = urlToProcess.indexOf(':');
        if (pos >= 0) {
            urlToProcess = urlToProcess.substring(0, pos);
        }

        // If we have resource location in the address then we strip
        // everything after the '/'
        pos = urlToProcess.indexOf('/');
        if (pos >= 0) {
            urlToProcess = urlToProcess.substring(0, pos);
        }

        // If we have ? in the address then we strip
        // everything after the '?'
        pos = urlToProcess.indexOf('?');
        if (pos >= 0) {
            urlToProcess = urlToProcess.substring(0, pos);
        }
        return urlToProcess;
    }

    /**
     * Transform host name in int value used by {@link ConnectivityManager.requestRouteToHost}
     * method
     *
     * @param hostname
     * @return -1 if the host doesn't exists, elsewhere its translation
     * to an integer
     */
    private int lookupHost(String hostname) {
        InetAddress inetAddress;
        try {
            inetAddress = InetAddress.getByName(hostname);
        } catch (UnknownHostException e) {
            return -1;
        }
        byte[] addrBytes;
        int addr;
        addrBytes = inetAddress.getAddress();
        addr = ((addrBytes[3] & 0xff) << 24)
                | ((addrBytes[2] & 0xff) << 16)
                | ((addrBytes[1] & 0xff) << 8 )
                |  (addrBytes[0] & 0xff);
        return addr;
    }

    @SuppressWarnings("unused")
    private int lookupHost2(String hostname) {
        InetAddress inetAddress;
        try {
            inetAddress = InetAddress.getByName(hostname);
        } catch (UnknownHostException e) {
            return -1;
        }
        byte[] addrBytes;
        int addr;
        addrBytes = inetAddress.getAddress();
        addr = ((addrBytes[3] & 0xff) << 24)


        | ((addrBytes[2] & 0xff) << 16)
            | ((addrBytes[1] & 0xff) << 8 )
            |  (addrBytes[0] & 0xff);
        return addr;
    }

    public Boolean disableWifi() {
        wifiMan = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        if (wifiMan != null) {
            wifiLock = wifiMan.createWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, "HelianRCAWifiLock");
        }
        return wifiMan.setWifiEnabled(false);
    }

    public Boolean enableWifi() {
        Boolean success = false;

        if (wifiLock != null && wifiLock.isHeld())
            wifiLock.release();
        if (wifiMan != null)
        success = wifiMan.setWifiEnabled(true);
        return success;
    }
}

This is the usage:

USAGE CODE

            boolean mobileRoutingEnabled = checkMobileInternetRouting();

            if(!mobileRoutingEnabled) {
                networkUtils.disableWifi();

                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            networkUtils.forceMobileConnectionForAddress(context, RCA_URL);

            if(!mobileRoutingEnabled) {
                networkUtils.enableWifi();
            }

            // This second check is for testing purpose
            checkMobileInternetRouting();

            return callWebService(RCA_COMPLETE_URL, _plate);

where checkMobileInternetRouting is:

private boolean checkMobileInternetRouting() {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    State state = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState();
    return 0 == state.compareTo(State.CONNECTED) || 0 == state.compareTo(State.CONNECTING);
}

USAGE PROCEDURE

  1. Check if the routing to the host is enabled
  2. If yes go with the communication regardless the wifi is connected or not and execute only points 6 (the point 4 will only check that routing is already enable without executing any rilevant action). Otherwise temporary disables the wifi.
  3. Thread sleep of about 3 seconds for letting the 3g connection comes back
  4. Set the 3g routing to the given url
  5. Enable back the wifi
  6. Now the given url can be called even with a wifi connection without net acces

CONCLUSIONS

This is a bit hacky but works properly. The only problem is that this routing has got a timeout of few seconds (like 20-30) that forces you to execute the entire above procedure once more. Setting this timeout to a higher value would be very good.

这篇关于力的Andr​​oid使用3G的时候就没有网络接入局域无线上网的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆