java - validar - ¿Impedir que el teléfono Android se conecte a la red WiFi a menos que mi aplicación lo apruebe?
verificar conexion a internet android studio (3)
Quiero desarrollar una aplicación que pueda evitar la conexión a una red WiFi a menos que la apruebe. Quiero poder consultar la dirección MAC del punto de acceso y compararla con una lista de direcciones conocidas correspondientes a los SSID. El objetivo de la aplicación es proteger a los usuarios de conectarse accidentalmente a puntos de acceso maliciosos, como los tipos que se pueden producir con dispositivos de piña .
De mi investigación no tengo claro cómo lograría este objetivo. Preguntas como ¿Cómo ser notificado sobre el cambio de estado de la red wifi? explique cómo detectar la conexión que ha ocurrido , pero para mi caso de uso ya es demasiado tarde.
Ni ConnectivityManager
ni WifiManager
parecen ofrecer métodos para agregar oyentes que podrían interrumpir una conexión en curso.
Algunos pensamientos que he tenido para una solución:
Instáleme como un proxy y tome la decisión de permitir el paso de los datos. Sin embargo, esto no parece ser una opción basada en ¿Se aplican las configuraciones de proxy de Android a todas las aplicaciones en el dispositivo? (pista: la respuesta es "No").
Reemplazar el administrador de WiFi existente con algo de mi propia creación. Sin embargo, me ha costado mucho encontrar información en las guías para desarrolladores de Android para reemplazar componentes del sistema. En consecuencia, no estoy seguro de que esto sea posible en teléfonos no rooteados.
Almacene las contraseñas de red dentro de mi aplicación y establezca las contraseñas en el administrador de WiFi en valores sin sentido.Luego capture un mensaje de difusión que advierta sobre una conexión fallida (probablemente algo comoWifiManager.WPS_AUTH_FAILURE
) y decida volver a conectarse a esa red de forma selectiva.Podría ser una solución posible (aunque fea), pero ¿puedo restablecer la contraseña a un valor sin sentido mientras la red aún está conectada, para garantizar que no nos conectemos silenciosamente a otro SSID del mismo nombre?No estoy seguroSe me ocurre que los dispositivos de piña probablemente aceptarían cualquier contraseña, por lo que este enfoque quedaría sin efecto.Encuentre alguna forma de evitar que Android se conecte automáticamente a redes conocidas (es decir, redes que se han usado antes o que tienen una contraseña almacenada con ellas). Entonces podría administrar todas las conexiones / desconexiones de mi aplicación. Sin embargo, no puedo ver cómo hacer esto manualmente en mi teléfono, así que dudo que esto sea posible mediante programación.
¿Alguien puede sugerir un enfoque que funcione en un teléfono no rooteado?
No se puede implementar un sistema muy robusto sin rootear el dispositivo. Aquí está lo más cerca que puedes llegar, creo:
- Use getConfiguredNetworks() para obtener una lista de las redes configuradas actualmente en el dispositivo del usuario
- Para cada WifiConfiguration de WifiConfiguration en la lista, configure el BSSID campo público a la dirección MAC "segura" deseada
- Llame a saveConfiguration() para persistir los cambios
Alternativamente, para el paso (2), puede llamar a disableNetwork() para cada red configurada y habilitarlos de forma selectiva según el BSSID. Tenga en cuenta que las direcciones MAC todavía pueden ser falsificadas con bastante facilidad.
como se sabe al conectarse a Wifi, la aplicación sifi manager muestra un mensaje de sugerencia bajo el nombre de Wifi que se está conectando,
Como conectar, autenticar, obtener IP ... etc
así que traté de buscar cómo puedo detectar esas etapas de conexión a una red Wifi. SUPPLICANT_STATE_CHANGED_ACTION
a una respuesta que muestra cómo se hace esto. Se hizo usando un receptor para SUPPLICANT_STATE_CHANGED_ACTION
e intenté implementarlo agregando el código para simplemente desconectar ... y eso fue un éxito ya que el Wifi nunca se conectó, el ícono no apareció en la barra de notificaciones y los registros siguen repitiendo los pasos, aunque en cierta forma se dice que está conectado en los registros) pero en realidad no aparece nada en el propio dispositivo, así que tal vez se conectó para like (10 MS)
De todos modos, debajo está el código que usé:
public class MyNetworkMonitor extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// EXTRA_BSSID
// SUPPLICANT_STATE_CHANGED_ACTION
// EXTRA_NEW_STATE
// Log.i("YAZAN", intent.getAction() + " " +
// intent.getStringExtra(WifiManager.EXTRA_BSSID));
// Log.i("YAZAN", intent.getAction() + " "
// +intent.getStringExtra(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION));
// Log.i("YAZAN", intent.getAction() + " "
// +intent.getStringExtra(WifiManager.EXTRA_NEW_STATE));
//Log.i("YAZAN", intent.getAction() + " " + intent.getStringExtra(WifiManager.EXTRA_BSSID));
String action = intent.getAction();
if(action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)){
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
Log.d("YAZAN", ">>>>SUPPLICANT_STATE_CHANGED_ACTION<<<<<<");
SupplicantState supl_state=((SupplicantState)intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE));
switch(supl_state){
case ASSOCIATED:Log.i("YAZAN", "ASSOCIATED");
break;
case ASSOCIATING:
Log.i("YAZAN", "ASSOCIATING");
wifi.disconnect();
Log.i("YAZAN", "disconnect()");
break;
case AUTHENTICATING:Log.i("YAZAN", "Authenticating...");
wifi.disconnect();
Log.i("YAZAN", "disconnect()");
break;
case COMPLETED:Log.i("YAZAN", "Connected");
break;
case DISCONNECTED:Log.i("YAZAN", "Disconnected");
break;
case DORMANT:Log.i("YAZAN", "DORMANT");
wifi.disconnect();
Log.i("YAZAN", "disconnect()");
break;
case FOUR_WAY_HANDSHAKE:Log.i("YAZAN", "FOUR_WAY_HANDSHAKE");
wifi.disconnect();
Log.i("YAZAN", "disconnect()");
break;
case GROUP_HANDSHAKE:Log.i("YAZAN", "GROUP_HANDSHAKE");
wifi.disconnect();
Log.i("YAZAN", "disconnect()");
break;
case INACTIVE:Log.i("YAZAN", "INACTIVE");
break;
case INTERFACE_DISABLED:Log.i("YAZAN", "INTERFACE_DISABLED");
break;
case INVALID:Log.i("YAZAN", "INVALID");
break;
case SCANNING:Log.i("YAZAN", "SCANNING");
break;
case UNINITIALIZED:Log.i("YAZAN", "UNINITIALIZED");
break;
default:Log.i("YAZAN", "Unknown");
break;
}
int supl_error=intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
if(supl_error==WifiManager.ERROR_AUTHENTICATING){
Log.i("YAZAN", "ERROR_AUTHENTICATING!");
}
}//if
}// onReceive()
donde quiera que encuentre un wifi.disconnect();
así es como interrumpí la conexión. lo que queda aquí es obtener el nombre de la red o la dirección mac para permitir o no permitir que el proceso se complete
Permisos:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
añadiendo el receptor de difusión:
<receiver android:name=".MyNetworkMonitor" >
<intent-filter>
<action android:name="android.net.wifi.supplicant.STATE_CHANGE" />
<action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
<action android:name="android.net.wifi.STATE_CHANGE" />
</intent-filter>
</receiver>
Gracias
puede escuchar el cambio de conectividad de wifi y actuar en esos eventos para habilitar la inhabilitación de wifi
private ConnectivityManager connectionManager;
boolean previousConnectivityStatus;
private WifiManager wifiManager;
/* Register Connectivity Receiver */
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
context.registerReceiver(networkBroadcastReceiver, intentFilter);
/* Register Wifi State Listener */
IntentFilter wifiStateIntentFilter = new IntentFilter();
wifiStateIntentFilter.addAction("android.net.wifi.WIFI_STATE_CHANGED");
context.registerReceiver(wifiStateReceiver, wifiStateIntentFilter);
connectionManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
private BroadcastReceiver wifiStateReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
Utility.traceM("NetworkController.wifiStateReceiver.new BroadcastReceiver() {...}::onReceive");
int extraWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN);
switch (extraWifiState)
{
case WifiManager.WIFI_STATE_DISABLED:
{
Utility.trace("Broadcast Wifi State Disabled");
if(isWifiStateEventsEnabled)
{
EventBus.getDefault().post(new NetworkEvent(NetworkEventType.WIFI_DISABLED));
}
break;
}
case WifiManager.WIFI_STATE_ENABLED:
{
Utility.trace("Broadcast Wifi State Enabled");
if(isWifiStateEventsEnabled)
{
EventBus.getDefault().post(new NetworkEvent(NetworkEventType.WIFI_ENABLED));
}
break;
}
}
}
};
private BroadcastReceiver networkBroadcastReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
Utility.traceM("NetworkController.networkBroadcastReceiver.new BroadcastReceiver() {...}::onReceive");
boolean connectivityStatus = isInternetConnectivityAvailable();
if (previousConnectivityStatus != connectivityStatus)
{
if (connectivityStatus)
{
previousConnectivityStatus = true;
Utility.trace("Broadcast Internet Available");
EventBus.getDefault().post(new NetworkEvent(NetworkEventType.INTERNET_CONNECTED));
}
else
{
previousConnectivityStatus = false;
Utility.trace("Broadcast Internet Disconnected");
EventBus.getDefault().post(new NetworkEvent(NetworkEventType.INTERNET_DISCONNECTED));
}
}
}
};