可达性和国际漫游

我使用Apple的Reachability类来确定数据或wifi是否可用。 但是,用户(使用美国iPhone)正在testing另一个国家/地区的应用程序,并在尝试访问MapKit时看到以下错误。

安慰

在我对这个错误的研究中,我发现PBRequesterProtocolBuffer

2012-10-15 21:16:00.921 WrightsCS应用程序[24239:907] PBRequester失败,错误错误域= kCFErrorDomainCFNetwork代码= -1018“国际漫游目前closures。 UserInfo = 0x1e5587d0 {NSErrorFailingURLKey = https://gsp13-cn.ls.apple.com/shift,NSErrorFailingURLStringKey = https://gsp13-cn.ls.apple.com/shift,NSLocalizedDescription =国际漫游目前closures。}

 -(BOOL)hasDataConnection { Reachability *networkReachability = [Reachability reachabilityForInternetConnection]; NetworkStatus networkStatus = [networkReachability currentReachabilityStatus]; if ( networkStatus == NotReachable ) { return NO; } else { if ( ! [Reachability reachabilityWithHostName:@"www.google.com"] ) return NO; return YES; } } 

我们如何才能检测用户是否在漫游,或者至less确保我们没有遇到这个错误,如果偶然的用户漫游?

好的 – 这不是一个答案,但可能会指出你在正确的方向。 首先,我找不到一个目标C类似乎让你这样做(例如NSURLRequest类)。

我认为你将需要直接进入CFNetwork框架(CFNetwork框架参考),因为看着CFNetworkError代码有这些诱人的条目(它符合你的错误信息):

 kCFURLErrorNotConnectedToInternet = -1009, kCFURLErrorInternationalRoamingOff = -1018, kCFURLErrorDataNotAllowed = -1020, 

不幸的是,我不知道CFNetwork框架,尽pipe看了苹果文档,我不明白哪个CFNetwork框架API使用这些值。 但我相信会有一个办法。

我的两个“思想”(我用这个词松散):

  1. 使用CFHost (并得到一个callback来查询错误代码)
  2. 使用CFNetDiagnosticCopyNetworkStatusPassively (并parsing返回的string)。

如果有专家,我很乐意看到真正的答案。

您可以使用http://ipinfo.io (我自己的服务)等第三方服务,根据设备的IP地址找出甚至载体代码的当前国家。 然后,您可以将其与CTCarrier详细信息进行比较,以确定设备是否正在漫游。 以下是标准的ipinfo.io API响应:

 $ curl ipinfo.io/24.32.148.1 { "ip": "24.32.148.1", "hostname": "doc-24-32-148-1.pecos.tx.cebridge.net", "city": "Pecos", "region": "Texas", "country": "US", "loc": "31.3086,-103.5892", "org": "AS7018 AT&T Services, Inc.", "postal": "79772" } 

自定义软件包也可以包含移动IP的mnc / mcc详细信息。 有关详细信息,请参阅http://ipinfo.io/developers

苹果实际上build议你不要使用可达性,如果你可以避免它,但只是打电话,并检查结果。 在通话之前,您可以将允许CellularAccess设置为NO,以避免昂贵的3G连接。

显然你会得到错误。 在3G可能但不允许的特殊情况下,如果没有WiFi,则会出现kCFURLErrorDataNotAllowed。 然后你可能会问用户是否想让你连接3G。

否则,如果没有互联网连接,你会得到kCFURLErrorNotConnectedToInternet,并在特殊情况下,将有3G连接,但不允许数据漫游(如美国电话在另一个国家),你会得到kCFURLErrorInternationalRoamingOff。 也有kCFURLErrorCallIsActive,你会得到一个电话,不能使用3G通话时。

我做了这个检查漫游(这不是100%充分的证据,但..):

1.首次在用户首次加载应用程序时,将运营商networking保存为用户默认值:

 CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init]; CTCarrier *carrier = [netinfo subscriberCellularProvider]; NSString *name = [[carrier carrierName] copy]; NSLog(@"Carrier Name: %@", name); NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults]; self.homeNetwork = [standardUserDefaults objectForKey:SNAP_homeNetwork]; if(self.homeNetwork == nil || self.homeNetwork.length == 0){ self.homeNetwork = [[Globals sharedInstance] getCarrier]; [standardUserDefaults setObject:self.homeNetwork forKey:SNAP_homeNetwork]; [standardUserDefaults synchronize]; } 
  1. 每次你需要检查currentCarrier Vs是你第一次启动应用程序时保存的,如果名称不同,那么用户正在漫游。