¿Cómo usar la conexión 3G en la aplicación de Android en lugar de Wi-Fi?

¿Cómo usar la conexión 3G en la aplicación de Android en lugar de Wi-Fi?

Quiero conectar una conexión 3G, ¿hay algún código de muestra para conectar a 3G en lugar de Wi-Fi?

La aplicación “Mi cuenta” de T-Mobile hace esto, si está conectado a una conexión WiFi, le dice que su progtwig no funcionará a través de WiFi y luego le pregunta al usuario si desea desactivar la conexión WiFi. Si elige ” No “luego la aplicación sale, si elige” Sí “, la aplicación desactiva su conexión WiFi y luego continúa con el inicio.

Creo que este es un buen modelo a seguir, ya que garantizará que su aplicación no se ejecute a través de WiFi y le permite al usuario decidir si quiere apagar la conexión WiFi o no. Una mejora en este modelo sería volver a encender wifi cuando el usuario navega fuera de su aplicación.

No he probado el siguiente código, pero parece que debería funcionar (modificado desde aquí )

usa los siguientes permisos en tu manifiesto

  

y aquí hay un código real para activar / desactivar wifi

 private WifiManager wifiManager; @Override public void onCreate(Bundle icicle) { .................... wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE); if(wifiManager.isWifiEnabled()) { wifiManager.setWifiEnabled(false); } else { wifiManager.setWifiEnabled(true); } } 

Si no desea ir por esa ruta, parece que podría decirle al teléfono que preferiría usar la red de datos móviles en lugar de la red wifi.

Android ConnectivityManager ofrece una función setNetworkPreference . Esta función no está realmente documentada ya que puede ver si hace clic en el enlace. Sin embargo, me gustaría dar vueltas con eso porque las constantes que se definen parecen indicar que puede establecer esto en TYPE_MOBILE o TYPE_WIFI y también hay una constante DEFAULT_NETWORK_PREFERENCE que se define como 0x00000001 que es lo mismo que TYPE_WIFI. Intente obtener acceso a ConnectivityManager llamando

 Context.getSystemService(Context.CONNECTIVITY_SERVICE); 

y luego intente usar la función setNetworkPreference ().

No parece requerir ningún permiso en el manifiesto, pero puede requerir el permiso CHANGE_NETWORK_STATE o algo similar.

Si demanda la función setNetworkPreference, probablemente sea mejor establecer también la Preferencia de Red a sus valores originales (recibidos de getNetworkPreference)

Espero que esto ayude.

 /** * 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 */ private boolean forceMobileConnectionForAddress(Context context, String address) { ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (null == connectivityManager) { Log.debug(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.debug(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.debug(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.error(TAG_LOG, "Wrong result of startUsingNetworkFeature, maybe problems"); return false; } if (0 == resultInt) { Log.debug(TAG_LOG, "No need to perform additional network settings"); return true; } //find the host name to route String hostName = StringUtil.extractAddressFromUrl(address); Log.debug(TAG_LOG, "Source address: " + address); Log.debug(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.error(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.debug(TAG_LOG, "requestRouteToHost result: " + resultBool); if (!resultBool) Log.error(TAG_LOG, "Wrong requestRouteToHost result: expected true, but was false"); return resultBool; } 

Y esto para calcular la dirección del host:

 /** * This method extracts from address the hostname * @param url eg. http://some.where.com:8080/sync * @return some.where.com */ public static 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 static 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; } 

Y se debe agregar el siguiente permiso a AndroidManifest.xml

   

Funciona solo con Android 2.2 y versiones posteriores, probado tanto en Nexus One como en LG Optimus, otros teléfonos que no conozco porque algunos métodos de ConnectivityMananger son específicos del proveedor. Después de 15-20 segundos de inactividad, la red móvil se desconecta automáticamente.

Creo que eso no es posible desde Java. El sistema cierra todas las comunicaciones basadas en la red móvil si está conectado a una red inalámbrica. Creo que no puedes iniciar una conexión 3G desde tu progtwig.

Aquí está el código que funciona en API 21+ (Lollipop, Marshmallow ..). Prefiero usar OkHttp con Network.getSocketFactory () , pero Network.openURLConnection () también funciona bien.

 private void doTest() { display("Requesting CELLULAR network connectivity..."); ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); NetworkRequest request = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build(); connectivityManager.requestNetwork(request, new ConnectivityManager.NetworkCallback() { /** * Called when the framework connects and has declared a new network ready for use. * This callback may be called more than once if the {@link Network} that is * satisfying the request changes. * * This method will be called on non-UI thread, so beware not to use any UI updates directly. * * @param network The {@link Network} of the satisfying network. */ @Override public void onAvailable(final Network network) { display("Got available network: " + network.toString()); try { final InetAddress address = network.getByName("navalclash.com"); display("Resolved host2ip: " + address.getHostName() + " -> " + address.getHostAddress()); } catch (UnknownHostException e) { e.printStackTrace(); } display("Do request test page from remote http server..."); if(okHttpClient == null) { okHttpClient = new OkHttpClient.Builder().socketFactory(network.getSocketFactory()).build(); } Request request = new Request.Builder() .url("http://navalclash.com") .build(); try (Response response = okHttpClient.newCall(request).execute()) { display("RESULT:\n" + response.body().string()); } catch (Exception ex) { ex.printStackTrace(); } } }); } 

use el administrador de conexión y establezca la preferencia de red como lo desee. buena suerte

por ejemplo: dataManager = (ConnectivityManager) getSystemService (CONNECTIVITY_SERVICE); dataManager.setNetworkPreference (ConnectivityManager.TYPE_MOBILE);

¡Esta aplicación activa la conexión 3G y Wifi, dando preferencia a 3G! Muy útil http://www.redrails.com.br/2012/02/wireless-analyzer-for-android/

Inspirado por el código en este ticket y usando algunas partes del mismo, este es un servicio que establece hipri mobile y lo mantiene en funcionamiento.

 import java.net.InetAddress; import java.net.UnknownHostException; import java.util.concurrent.atomic.AtomicBoolean; import android.app.Service; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo.State; import android.os.IBinder; import android.util.Log; public class HipriService extends Service { private AtomicBoolean enabledMobile = new AtomicBoolean(false); public boolean enableMobileConnection() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); if (null == cm) { Log.d(TAG, "ConnectivityManager is null, cannot try to force a mobile connection"); return false; } /* * Don't do anything if we are connecting. On the other hands re-new * connection if we are connected. */ State state = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState(); Log.d(TAG, "TYPE_MOBILE_HIPRI network state: " + state); if (0 == state.compareTo(State.CONNECTING)) return true; /* * Re-activate mobile connection in addition to other connection already * activated */ int resultInt = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI"); //Log.d(TAG, "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, "Wrong result of startUsingNetworkFeature, maybe problems"); return false; } if (0 == resultInt) { Log.d(TAG, "No need to perform additional network settings"); return true; } return requestRouteToHost(this, Uploader.ServerAddress); } private Thread pingerThread = null; private void startMobileConnection() { enabledMobile.set(true); pingerThread = new Thread(new Runnable() { @Override public void run() { while (enabledMobile.get()) { /* * Renew mobile connection. No routing setup is needed. This * should be moved to 3g monitoring service one day. */ enableMobileConnection(); try { Thread.sleep(1000); } catch (InterruptedException e) { // do nothing } } } }); pingerThread.start(); } private void stopMobileConnection() { enabledMobile.set(false); disableMobileConnection(); pingerThread.interrupt(); pingerThread = null; } public void disableMobileConnection() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, "enableHIPRI"); } public final static int inetAddressToInt(InetAddress inetAddress) { 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 final static InetAddress lookupHost(String hostname) { try { return InetAddress.getByName(hostname); } catch (UnknownHostException e) { return null; } } private boolean requestRouteToHost(Context context, String hostname) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (null == cm) { Log.d(TAG, "ConnectivityManager is null, cannot try to force a mobile connection"); return false; } /* Wait some time needed to connection manager for waking up */ try { for (int counter = 0; enabledMobile.get() && counter < 30; counter++) { State checkState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState(); Log.i(TAG, "Waiting for mobile data on. State " + checkState); if (0 == checkState.compareTo(State.CONNECTED)) break; Thread.sleep(1000); } } catch (InterruptedException e) { //nothing to do } if (!enabledMobile.get()) { Log.d(TAG, "Mobile data is turned off while waiting for routing."); return false; } State checkState = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_HIPRI).getState(); if (0 != checkState.compareTo(State.CONNECTED)) { Log.e(TAG, "Mobile data is still turned off after 30 sec of waiting."); return false; } Log.i(TAG, "Adding routing for " + hostname); InetAddress inetAddress = lookupHost(hostname); if (inetAddress == null) { Log.e(TAG, "Failed to resolve " + hostname); return false; } int hostAddress = inetAddressToInt(inetAddress); boolean resultBool = cm.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, hostAddress); Log.d(TAG, "requestRouteToHost result: " + resultBool); if (!resultBool) Log.e(TAG, "Wrong requestRouteToHost result: expected true, but was false"); return resultBool; } @Override public void onCreate() { super.onCreate(); startMobileConnection(); } @Override public void onDestroy() { stopMobileConnection(); super.onDestroy(); } @Override public IBinder onBind(Intent intent) { return null; } } 

Aquí es cómo lo comienzo / detengo cuando sea necesario. Tenga en cuenta que también se bloquea en la CPU y wifi para que se ejecute cuando el teléfono duerme (solo en la pantalla). Se necesita Wifi porque mi aplicación es una especie de puente entre wifi y conexiones móviles. Puede que no lo necesites.

 public void startMobileData() { if (!enabledMobile.get()) { enabledMobile.set(true); WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE); wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL, "Wifi Wakelock"); wifiLock.acquire(); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); partialLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "3G Wakelock"); partialLock.acquire(); startService(new Intent(this, HipriService.class)); } } public void stopMobileData() { if (enabledMobile.get()) { enabledMobile.set(false); Log.i(TAG, "Disabled mobile data"); stopService(new Intent(this, HipriService.class)); if (partialLock != null) { partialLock.release(); partialLock = null; } if (wifiLock != null) { wifiLock.release(); wifiLock = null; } } } 

No olvides agregar servicio a tu archivo de manifiesto.

@umka

  • Creo que la aplicación solo puede llegar a esos hosts a través de HIPRI que ha solicitado, puede ser para otros hosts (cuyas rutas no son solicitadas) está utilizando la red predeterminada (MOBILE o WIFI).
  • Al llamar a stopUsingNetworkFeature () , comprobará: ¿hay alguna otra aplicación que esté utilizando esta red, si es así, ignorará su solicitud para desactivar esta característica de red.
  • uno de los principales propósitos de la red HIPRI es que, si el wifi está encendido y una aplicación desea usar la red móvil (3G) para llegar al host en particular, puede acceder a través de la red HIPRI.

Falta un fragmento de código en la respuesta @Northern Captain, el código de búsqueda de DNS.

Aquí hay un código de trabajo:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Log.d("NetworkDns", "Requesting CELLULAR network connectivity..."); NetworkRequest request = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build(); connectivityManager.requestNetwork(request, new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(final Network network) { Log.d("NetworkDns", "Got available network: " + network.toString()); try { final InetAddress address = network.getByName("www.website.com"); Log.d("NetworkDns", "Resolved host2ip: " + address.getHostName() + " -> " + address.getHostAddress()); } catch (UnknownHostException e) { e.printStackTrace(); } Log.d("NetworkDns", "Do request test page from remote http server..."); OkHttpClient okHttpClient = null; if(okHttpClient == null) { okHttpClient = new OkHttpClient.Builder() .socketFactory(network.getSocketFactory()) .dns(new Dns() { @Override public List lookup(String hostname) throws UnknownHostException { if (network != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { List addresses = Arrays.asList(network.getAllByName(hostname)); Log.d("NetworkDns", "List : " + addresses); return addresses; } return SYSTEM.lookup(hostname); } }).build(); } Request request = new Request.Builder() .url("http://www.website.com") .build(); try (Response response = okHttpClient.newCall(request).execute()) { Log.d("NetworkDns", "RESULT:\n" + response.body().string()); } catch (Exception ex) { ex.printStackTrace(); } } }); }