iOS检测3G或WiFi

时间:2011-10-29 11:34:56

标签: ios objective-c wifi reachability 3g

我不确定这是否可行,但我有这种情况。

我的UIWebView中显示了一个网站,该网站在UISegmentedController中设置了链接。 他们的网站可以检测您是在wifi上还是在3g网络上。

现在分段控制器指向2个不同的页面: 1 - iPhone友好的登录屏幕 2 - 登录后的主页。

现在问题是:

我是否可以对我的应用程序进行编程以检测它是WIFI还是3G(我知道你可以这样做),但是根据答案转到第1段或第2段

有点像这样:

if (iPhone device is on 3g) {
    Go to Segment 1;
} else {
    Go to Segment 0;
}

13 个答案:

答案 0 :(得分:208)

使用Apple提供的代码here

Reachability *reachability = [Reachability reachabilityForInternetConnection];
[reachability startNotifier];

NetworkStatus status = [reachability currentReachabilityStatus];

if(status == NotReachable) 
{
    //No internet
}
else if (status == ReachableViaWiFi)
{
    //WiFi
}
else if (status == ReachableViaWWAN) 
{
    //3G
}

答案 1 :(得分:28)

如果您不想导入Reachability库或处理通知程序,可以使用这种简单的同步方法:

typedef enum {
    ConnectionTypeUnknown,
    ConnectionTypeNone,
    ConnectionType3G,
    ConnectionTypeWiFi
} ConnectionType;


+ (ConnectionType)connectionType
{
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, "8.8.8.8");
    SCNetworkReachabilityFlags flags;
    BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
    CFRelease(reachability);
    if (!success) {
        return ConnectionTypeUnknown;
    }
    BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0);
    BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0);
    BOOL isNetworkReachable = (isReachable && !needsConnection);

    if (!isNetworkReachable) {
        return ConnectionTypeNone;
    } else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
        return ConnectionType3G;
    } else {
        return ConnectionTypeWiFi;
    }
}

答案 2 :(得分:18)

导入Apple的Reachability并尝试此操作

#import "Reachability.h"
#import <CoreTelephony/CTTelephonyNetworkInfo.h>

//Try this
Reachability *reachability = [Reachability reachabilityForInternetConnection];
    [reachability startNotifier];

    NetworkStatus status = [reachability currentReachabilityStatus];

    if(status == NotReachable)
    {
       NSLog(@"none");
        //No internet
    }
    else if (status == ReachableViaWiFi)
    {
        NSLog(@"Wifi");
        //WiFi
    }
    else if (status == ReachableViaWWAN)
    {
        NSLog(@"WWAN");


    //connection type
    CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init];
    _carrier = [[netinfo subscriberCellularProvider] carrierName];

    if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS]) {
        NSLog(@"2G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge]) {
        NSLog(@"2G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyWCDMA]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSDPA]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSUPA]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x]) {
        NSLog(@"2G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyeHRPD]) {
        NSLog(@"3G");
    } else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE]) {
        NSLog(@"4G");
    }

    }

参考文献(未来链接可能会破裂):

答案 3 :(得分:8)

我制作了一个非常简单的基于块的Reachability包装器,它剥离了所有过时的C-like Reachability代码,并将其倾注到更多Cocoa形式。

用法如:

[EPPZReachability reachHost:hostNameOrIPaddress
               completition:^(EPPZReachability *reachability)
{
    if (reachability.reachableViaCellular) [self doSomeLightweightStuff];
}];

Reachability with blocks for everyday use上查看eppz!blog,或直接从eppz!reachability at GitHub抓取。

也适用于IP地址,后来证明这是一种非常罕见的可达性包装功能。

答案 4 :(得分:5)

对于swift,我们可以使用:

func getNetworkType()->String {
    do{
        let reachability:Reachability = try Reachability.reachabilityForInternetConnection()
        do{
            try reachability.startNotifier()
            let status = reachability.currentReachabilityStatus
            if(status == .NotReachable){
                return ""
            }else if (status == .ReachableViaWiFi){
                return "Wifi"
            }else if (status == .ReachableViaWWAN){
                let networkInfo = CTTelephonyNetworkInfo()
                let carrierType = networkInfo.currentRadioAccessTechnology
                switch carrierType{
                case CTRadioAccessTechnologyGPRS?,CTRadioAccessTechnologyEdge?,CTRadioAccessTechnologyCDMA1x?: return "2G"
                case CTRadioAccessTechnologyWCDMA?,CTRadioAccessTechnologyHSDPA?,CTRadioAccessTechnologyHSUPA?,CTRadioAccessTechnologyCDMAEVDORev0?,CTRadioAccessTechnologyCDMAEVDORevA?,CTRadioAccessTechnologyCDMAEVDORevB?,CTRadioAccessTechnologyeHRPD?: return "3G"
                case CTRadioAccessTechnologyLTE?: return "4G"
                default: return ""
                }

                // Get carrier name

            }else{
                return ""
            }
        }catch{
            return ""
        }

    }catch{
        return ""
    }


}

答案 5 :(得分:2)

#import <ifaddrs.h>
#import <arpa/inet.h>

BOOL CheckWiFi() {

    struct ifaddrs *interfaces = NULL;
    struct ifaddrs *temp_addr = NULL;

    BOOL hasWifi = NO;

    int err = getifaddrs(&interfaces);
    if(err == 0) {

        temp_addr = interfaces; 

        while(temp_addr) {

            if(temp_addr->ifa_addr->sa_family == AF_INET) {

                struct sockaddr_in *addr = (struct sockaddr_in *)temp_addr->ifa_addr;

                if(memcmp(temp_addr->ifa_name, "en", 2) == 0) {
                    hasWifi = YES;
                    break;
                }
            }

            temp_addr = temp_addr->ifa_next;
        }
    }

    freeifaddrs(interfaces);
    return hasWifi;
}

要检查您是否在wifi中,这可以节省昂贵的连接检查。检查ifa_name“bridge”以检查互联网共享。

答案 6 :(得分:2)

类方法如下

+(NSString*)connectedNetworkType {
     Reachability *reachability = [Reachability reachabilityForInternetConnection];
        [reachability startNotifier];

        NetworkStatus status = [reachability currentReachabilityStatus];

        if(status == NotReachable) {
            NSLog(@"none");
            //No internet
        }
        else if (status == ReachableViaWiFi) {
            NSLog(@"Wifi");
            //WiFi
            return @"Wifi";
        }
        else if (status == ReachableViaWWAN){
            NSLog(@"WWAN");
            //connection type
            CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init];
            //    _carrier = [[netinfo subscriberCellularProvider] carrierName];
            if (([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS])
                ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge])
                ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x])) {
                NSLog(@"2G");
                return @"2G";
            }
            else if (([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyWCDMA])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSDPA])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSUPA])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB])
                     ||([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyeHRPD])){
                NSLog(@"3G");
                return @"3G";
            }
            else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE]) {
                NSLog(@"4G");
                return @"4G";

            }
        }
        return @"-1";//default unknown
}

答案 7 :(得分:1)

如果您使用的是Xamarin或Monotouch,可以使用Xamarin GitHub存储库中的Reachability改编类:

https://github.com/xamarin/monotouch-samples/blob/master/ReachabilitySample/reachability.cs

然后将其添加到您的项目中并致电Reachability.InternetConnectionStatus()

答案 8 :(得分:1)

在使用iOS 12或更高版本时,可以使用NWPathMonitor代替史前的Reachability类:

import Network // Put this on top of your class

let monitor = NWPathMonitor()

monitor.pathUpdateHandler = { path in
    if path.status != .satisfied {
        // Not connected
    }
    else if path.usesInterfaceType(.cellular) {
        // Cellular 3/4/5g connection
    }
    else if path.usesInterfaceType(.wifi) {
        // Wi-fi connection
    }
    else if path.usesInterfaceType(.wiredEthernet) {
        // Ethernet connection
    }
}

monitor.start(queue: DispatchQueue.global(qos: .background))

答案 9 :(得分:1)

如果您不想使用可达性或使用Swift,那么简单的答案就在这里

https://stackoverflow.com/a/63837522/6342609

答案 10 :(得分:1)

支持 5G 的 Swift 版本;基于几个答案。

import Foundation
import SystemConfiguration
import CoreTelephony

/// Returns current network connection type(e.g. 4G, WIFI). It may take some time; so there is the suggestion not to use it on the main queue.
static func connectionType() -> ConnectionType {
    guard let reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, "www.google.com") else {
        return .noConnection
    }
    
    var flags = SCNetworkReachabilityFlags()
    SCNetworkReachabilityGetFlags(reachability, &flags)
    
    guard flags.contains(.reachable) else { return .noConnection }
    guard flags.contains(.isWWAN) else { return .wifi }
    
    let networkInfo = CTTelephonyNetworkInfo()
    let carrierTypeName: String?
    
    if #available(iOS 12.0, *) {
        carrierTypeName = networkInfo.serviceCurrentRadioAccessTechnology?.first?.value
    } else {
        carrierTypeName = networkInfo.currentRadioAccessTechnology
    }
    
    if #available(iOS 14.0, *) {
        switch carrierTypeName {
            case CTRadioAccessTechnologyNR, CTRadioAccessTechnologyNRNSA:
                return .cellular5G
            default:
                break
        }
    }
    
    switch carrierTypeName {
        case CTRadioAccessTechnologyGPRS, CTRadioAccessTechnologyEdge, CTRadioAccessTechnologyCDMA1x:
            return .cellular2G
        case CTRadioAccessTechnologyLTE:
            return .cellular4G
        case nil:
            return .unknown
        default:
            return .cellular3G
    }
}

enum ConnectionType: CustomStringConvertible {
    case noConnection, unknown, wifi, cellular2G, cellular3G, cellular4G, cellular5G
        
    var description: String {
        switch self {
            case .noConnection:
                return "no connection"
            case .unknown:
                return "unknown"
            case .wifi:
                return "WIFI"
            case .cellular2G:
                return "2G"
            case .cellular3G:
                return "3G"
            case .cellular4G:
                return "LTE"
            case .cellular5G:
                return "5G"
        }
    }
}

答案 11 :(得分:0)

这是iOS 6的更新版本,其中包括来自苹果的SimplePing。它与ARC兼容,我从另一个人对Reachability的修复开始。 http://elbsolutions.com/projects/reachability-with-simpleping-wrapper/

我希望这有助于某人。

答案 12 :(得分:-2)

使用这个,使用Reachability构建并且易于使用,只需几行代码即可集成。有一个回调函数可以告诉你何时连接发生了变化 http://huytd.github.io/datatify/