Forzar Android a usar 3G cuando en el área local wifi sin acceso a la red

Tengo una configuración de LAN wifi que no tiene acceso a Internet. Sólo varios otros dispositivos wifi locales conectados a ella. El DHCP está configurado para no devolver un servidor de puerta de enlace o dns. Sólo un IP y una máscara de red.

Cuando conecto mi androide a este AP del wifi conecta bien, pero toda la conectividad del Internet en el teléfono para de trabajar.

Me esperaba que ya que el wifi no tiene configuración de pasarela que android debe darse cuenta de que el Internet no puede pasar por esa conexión y en su lugar debe ser enrutada a través de la conexión 3G que está en 5 bares.

He intentado establecer una IP estática en el teléfono Android, así, pero esto no ayudó.

La principal razón de esta configuración es para que el dispositivo Android puede transferir datos de esta red remota a un servidor basado en Internet ya que puede conectarse a los dispositivos locales sin problema. Sin embargo, el lado 3G se rompe una vez que el wifi está configurado.

¿Alguna idea sobre cómo solucionar este problema?

Después de un poco de codificación y pruebas he fusionado Squonk y esta solución. Esta es la clase que he creado:

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

Este es el uso :

CÓDIGO DE USO

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

Donde checkMobileInternetRouting es:

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

PROCEDIMIENTO DE USO

  1. Compruebe si el enrutamiento al host está habilitado
  2. En caso afirmativo, vaya con la comunicación independientemente de que el wifi esté conectado o no y ejecute sólo los puntos 6 (el punto 4 sólo comprobará que el enrutamiento ya está habilitado sin ejecutar ninguna acción rilevante). De lo contrario, deshabilita el wifi.
  3. Tiempo de espera del hilo de aproximadamente 3 segundos para permitir que la conexión 3G vuelva
  4. Establezca el encaminamiento 3g a la url dada
  5. Habilitar el wifi
  6. Ahora el url dado se puede llamar incluso con una conexión wifi sin acceso de red

CONCLUSIONES

Esto es un poco hacky, pero funciona correctamente. El único problema es que este enrutamiento tiene un tiempo de espera de pocos segundos (como 20-30) que obliga a ejecutar todo el procedimiento anterior una vez más. Establecer este tiempo de espera a un valor más alto sería muy bueno.

De código, cuando detecta que no hay conectividad, puede apagar WiFi …

En cuanto a un ajuste, no hay ninguno (ninguna buena manera de comprobar si realmente hay conectividad universal y confiable). Pero algunos teléfonos hacen exactamente lo que usted describe automáticamente, como por ejemplo mi LG P-970.

(Nota: Android se desconecta de las redes móviles cuando se conecta a un WiFi, por lo que no hay manera de seguir conectado a un WiFi, pero la ruta de acceso a Internet a través de móviles, aunque Linux puede hacerlo ip route ... herramientas))

No puedo garantizar que esto funcione ya que es algo que solo he experimentado hace algún tiempo. Tuve una necesidad similar de usar 3G (u otra red móvil) cuando la red wifi-conectada no tenía ninguna ruta al mundo exterior.

El siguiente código debe eliminar la conexión wifi para permitir que la red móvil entre en juego. Tendrá que hacer varias pruebas a lo largo del camino y restablecer la conexión wifi de nuevo después …

 WifiManager wifiMan = null; WifiManager.WifiLock wifiLock = null; private Boolean disableWifi() { wifiMan = (WifiManager) getSystemService(Context.WIFI_SERVICE); if (wifiMan != null) { wifiLock = wifiMan.createWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, "MyWifiLock"); } return wifiMan.setWifiEnabled(false); } private Boolean enableWifi() { Boolean success; if (wifiLock != null) wifiLock.release(); if (wifiMan != null) success = wifiMan.setWifiEnabled(true); return success; } 

No es necesario codificar nada. Encontré una aplicación que hace exactamente esto. Usted puede configurar para desconectarse automáticamente del wifi si no hay Internet de esta conexión.

https://play.google.com/store/apps/details?id=com.nLabs.internetconnectivity&hl=es

  • Cómo obtener la dirección MAC en Android 6.0
  • Habilitación de WiFi en el emulador de Android
  • Android: Fuerza los datos que se envían a través de radio vs WiFi
  • Portal cautivo con hotspot android configurado mediante programación
  • WifiDirectActivity Alteración de la muestra: Transfiere un ArrayList <String> p2p
  • Conexión WiFi a través de Android
  • Cómo obtener la configuración del proxy WiFi en Android
  • Wifi conexión múltiple directa ad-hoc
  • Android 6.0 No se puede agregar WifiConfiguration si ya hay otra WifiConfiguration para ese SSID
  • Android 5.0 Lollipop y 4.4 KitKat ignora mi red WiFi, enableNetwork () es inútil
  • Cómo y qué establecer en Android WifiConfiguration.preSharedKey para conectarse a la red WPA2 PSK WiFi
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.