Enviar datos a través de wifi (no internet) cuando los datos móviles
Estoy desarrollando y aplicación que se conecta a un dispositivo de hardware a través de wifi (generado por el dispositivo) y enviar datos a través de una conexión de socket. El problema es que cuando se activan los datos móviles (3G / 4G), android intenta enviar los datos a través de él en lugar de enviarlo a través del wifi generado por el dispositivo, porque porque el wifi no tiene conexión a Internet. Estaba pensando en usar ConnectivityManager # setNetworkPreference () pero ha sido obsoleto en api 21.
¿Cómo puedo configurarlo para enviar datos utilizando el wifi generado por el dispositivo en lugar de la interfaz de datos móviles?
- ObjectInputStream - ¿Cómo esperar a nuevos datos?
- Comunicación de LocalSocket con el dominio de Unix en Android NDK
- Android - Socket del servidor
- La mejor manera de implementar Socket.io en android
- Sockets, Threads y Servicios en android, ¿cómo hacerlos trabajar juntos?
- Cómo pasar datos del servidor a la aplicación de Android: REST vs Sockets
- Tiempo de espera de conexión de socket Android
- No obtiene respuesta en la conexión de socket
- Socket de transferencia de una actividad a otra
- Crear SSLSocket por SSLSocketFactory con tiempo de espera de conexión establecido
- Enviar / Recibir archivo / imagen Socket C # Android
- ¿El zócalo del cliente androide, cómo leer datos?
- Segunda AsyncTask no se ejecuta
Después de un montón de investigación y tiempo tratando de entenderlo todo descubrí que esto no es posible en las versiones anteriores a Android 5.0 (Lollipop), el sistema operativo sólo mantiene una interfaz de red a la vez y las aplicaciones no tienen control Más allá de esto.
Así que para hacer esto en versiones mayores o iguales al Lollipop hice lo siguiente:
- Antes de hacer su conexión de socket verifique si android mayor o igual a Lollipop, en caso de que no es usted acaba de hacer lo que tiene que hacer normalmente;
-
En caso de que la versión sea igual o mayor a Lollipop, necesitas hacer algo como esto:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { final ConnectivityManager manager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkRequest.Builder builder; builder = new NetworkRequest.Builder(); //set the transport type do WIFI builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); manager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { manager.bindProcessToNetwork(network); } else { //This method was deprecated in API level 23 ConnectivityManager.setProcessDefaultNetwork(network); } try { //do a callback or something else to alert your code that it's ok to send the message through socket now } catch (Exception e) { e.printStackTrace(); } manager.unregisterNetworkCallback(this); } }); }
-
Después de que usted termine usted debe parar de atar el proceso con esto:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { ConnectivityManager manager = (ConnectivityManager) InovePlugApplication.getContext() .getSystemService(Context.CONNECTIVITY_SERVICE); manager.bindProcessToNetwork(null); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ConnectivityManager.setProcessDefaultNetwork(null); }
Esta respuesta me ayudó a saber cómo hacerlo https://stackoverflow.com/a/29837637/2550932 .
La red cambiará de nuevo a móvil después de setProcessDefaultNetwork a wifi, usted no puede enviar los datos grandes por esta manera, porque todos los zócalos creados de esta manera dejarán de trabajar. No encuentro una manera perfecta ahora, aquí está para la referencia solamente.
1.If usted puede conseguir el acceso de la raíz, hace esto antes de conectar con wifi:
Process process = runtime.exec("su"); DataOutputStream dataOutputStream = new DataOutputStream(process.getOutputStream()); dataOutputStream.writeBytes("settings put global captive_portal_server 127.0.0.1\n"); dataOutputStream.writeBytes("exit\n"); dataOutputStream.flush(); int status = process.waitFor();
Y eliminarlo después de enviar datos:
dataOutputStream.writeBytes("settings delete global captive_portal_server\n");
2.Si puede obtener permiso de WRITE_SECURE_SETTINGS:
Settings.Global.putString(getContentResolver(),"captive_portal_server","127.0.0.1");
O:
Settings.Global.putInt(getContentResolver(),"captive_portal_detection_enabled",0);
- Cómo adjuntar un PDF a un correo electrónico de la aplicación Android – El tamaño del archivo es cero
- Cómo sincronizar correctamente el código RenderScript de Android en Nvidia Shield