saber - ¿Cómo verificar la conexión Wi-Fi local(no solo la conexión celular) con el iPhone SDK?
itinerancia de datos iphone (5)
Consulte este enlace: http://developer.apple.com/iphone/library/samplecode/Reachability/
Tienes que estar registrado como desarrollador para descargar el código de muestra. También y es importante! La API de accesibilidad funciona para más de 3.0 SDK, se bloquea para versiones inferiores.
Por cierto, para el nuevo HIG, todas las aplicaciones que dependen de la conexión WiFi deben alertar al usuario sobre su ausencia, es decir, si el dispositivo no está conectado a Wifi, avise al usuario.
Actualmente estoy usando lo siguiente para verificar si hay Wi-Fi disponible para mi aplicación:
#import <SystemConfiguration/SystemConfiguration.h>
static inline BOOL addressReachable(const struct sockaddr_in *hostAddress);
BOOL localWiFiAvailable()
{
struct sockaddr_in localWifiAddress;
bzero(&localWifiAddress, sizeof(localWifiAddress));
localWifiAddress.sin_len = sizeof(localWifiAddress);
localWifiAddress.sin_family = AF_INET;
// IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
localWifiAddress.sin_addr.s_addr = htonl(IN_LINKLOCALNETNUM);
return addressReachable(&localWifiAddress);
}
static inline BOOL addressReachable(const struct sockaddr_in *hostAddress)
{
const SCNetworkReachabilityRef target =
SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault,
(const struct sockaddr *)hostAddress);
if (target != NULL)
{
SCNetworkReachabilityFlags flags = 0;
const BOOL reachable = SCNetworkReachabilityGetFlags(target, &flags);
CFRelease(target);
return reachable && (flags & kSCNetworkFlagsReachable);
}
return NO;
}
Esto, sin embargo, no devuelve NO como debería cuando el iPhone está conectado solo a una red celular pero no a una red Wi-Fi. ¿Alguien sabe cómo arreglar esto?
Editar
Así que esto es lo que terminé usando:
#import <arpa/inet.h> // For AF_INET, etc.
#import <ifaddrs.h> // For getifaddrs()
#import <net/if.h> // For IFF_LOOPBACK
BOOL localWiFiAvailable()
{
struct ifaddrs *addresses;
struct ifaddrs *cursor;
BOOL wiFiAvailable = NO;
if (getifaddrs(&addresses) != 0) return NO;
cursor = addresses;
while (cursor != NULL) {
if (cursor -> ifa_addr -> sa_family == AF_INET
&& !(cursor -> ifa_flags & IFF_LOOPBACK)) // Ignore the loopback address
{
// Check for WiFi adapter
if (strcmp(cursor -> ifa_name, "en0") == 0) {
wiFiAvailable = YES;
break;
}
}
cursor = cursor -> ifa_next;
}
freeifaddrs(addresses);
return wiFiAvailable;
}
Gracias "no perdonado" (y Matt Brown aparentemente).
Echa un vistazo a la clase de accesibilidad proporcionada por Apple. Esto le permite verificar qué conectividad tiene el dispositivo actualmente, entre Wi-Fi, celular o ninguno. Incluso puede registrarse para recibir notificaciones cuando cambie la conectividad.
Desafortunadamente, Google no funciona para mí en este momento, pero al buscar en Google "accesibilidad del iPhone" obtendrás lo que necesitas.
Primero, modifique su método addressReachable. En lugar de
return reachable && (flags & kSCNetworkFlagsReachable);
agregue lo siguiente:
BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0);
return (isReachable && !needsConnection) ? YES : NO;
Esta es la forma correcta de verificar si hay una conexión disponible. Ahora, si desea distinguir claramente entre celular y wifi, modifique su método para devolver un int y use lo siguiente
BOOL isReachable = ((flags & kSCNetworkFlagsReachable) != 0);
BOOL needsConnection = ((flags & kSCNetworkFlagsConnectionRequired) != 0);
if(isReachable && !needsConnection) // connection is available
{
// determine what type of connection is available
BOOL isCellularConnection = ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0);
NSString *wifiIPAddress = [self getWiFiIPAddress];
if(isCellularConnection)
return 1; // cellular connection available
if(wifiIPAddress)
return 2; // wifi connection available
}
else
return 0; // no connection at all
El método getWiFiIPAddress es cortesía de Matt Brown y se puede encontrar here .
Una cosa más. El indicador kSCNetworkReachabilityFlagsIsDirect puede indicarle si el tráfico de la red pasa por una puerta de enlace o si llega directamente. Esto puede ser útil en algunos casos.
El código funciona correctamente en el dispositivo. En el simulador, declarará que está conectado a través de wifi cuando está conectado a través del cable Ethernet, y declarará que no hay conexión si está conectado a través de wifi.
Versión rápida
import Foundation
import SystemConfiguration
public class Reachability {
class func isInternetAvailable() -> Bool {
let IPaddress = "google.com"//WebServicesUtil.sharedInstance.getHostIPAddress()
if let host_name = IPaddress.cStringUsingEncoding(NSASCIIStringEncoding) {
let reachability =
SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, host_name).takeRetainedValue()
var flags: SCNetworkReachabilityFlags = 0
if SCNetworkReachabilityGetFlags(reachability, &flags) == 0 {
return false
}
let isReachable = (flags & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return (isReachable && !needsConnection)
}
else {
return false
}
}
}
-(Bool)isDataSourceAvailableNow
{
BOOL isDataSourceAvailable;
bool success = false;
const char *host_name = [@"www.google.com" cStringUsingEncoding:NSASCIIStringEncoding];
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, host_name);
if (reachability)
{
SCNetworkReachabilityFlags flags;
success = SCNetworkReachabilityGetFlags(reachability, &flags);
isDataSourceAvailable = success && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired);
CFRelease(reachability);
} return isDataSourceAvailable;
}