Accessibilité et itinérance internationale

J'utilise la class Reachability d'Apple pour déterminer si datatables ou le wifi sont disponibles. Cependant, un user (avec un iPhone américain) teste l'application dans un autre pays et il voit l'erreur suivante en essayant d'accéder au MapKit.

Console

Dans mes searchs sur cette erreur, j'ai trouvé que PBRequester est ProtocolBuffer .

2012-10-15 21: 16: 00.921 WrightsCS App [24239: 907] PBRequester a échoué avec Erreur Erreur Domaine = kCFErrorDomainCFNetwork Code = -1018 "L'itinérance internationale est actuellement désactivée." UserInfo = 0x1e5587d0 {NSErrorFailingURLKey = https: //gsp13-cn.ls.apple.com/shift, NSErrorFailingURLSsortingngKey = https: //gsp13-cn.ls.apple.com/shift, NSLocalizedDescription = L'itinérance internationale est actuellement désactivée.}

Exemple

 -(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; } } 

Question

Comment pouvons-nous détecter si l'user est en itinérance ou au less nous assurer que nous ne rencontrons pas cette erreur si, par hasard, l'user est en itinérance?

OK – ce n'est pas une réponse mais peut vous pointer dans la bonne direction. Pour commencer, je ne trouve pas de class Objective C qui semble vous permettre de le faire (par NSURLRequest class NSURLRequest ).

Je pense que vous devrez aller directement au CFNetwork Framework (CFNetwork Framework Reference) parce que regarder les codes CFNetworkError a ces inputs alléchantes (qui correspondent à votre message d'erreur):

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

Malheureusement, je ne connais pas le CFNetwork Framework et malgré les documents Apple, je ne suis pas plus prudent sur les API CFNetwork Framework qui utilisent ces valeurs. Mais je suis convaincu qu'il y aura un moyen.

Mes deux "idées" (et j'utilise ce mot vaguement):

  1. Utilisez CFHost (et obtenez un callback pour interroger le code d'erreur)
  2. Utilisez CFNetDiagnosticCopyNetworkStatusPassively (et CFNetDiagnosticCopyNetworkStatusPassively la string renvoyée).

J'aimerais voir la vraie réponse s'il y a un expert là-bas.

Vous pouvez utiliser des services tiers tels que http://ipinfo.io (mon propre service) pour connaître le pays actuel du même code de transporteur en fonction de l'adresse IP de l'appareil. Vous pouvez ensuite comparer cela aux détails de CTCarrier pour déterminer si le périphérique est en itinérance. Voici la réponse API ipinfo.io standard:

 $ 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" } 

Des packages personnalisés sont disponibles qui incluent également les détails mnc / mcc des adresses IP mobiles. Voir http://ipinfo.io/developers pour plus de détails.

En fait, Apple vous recommand de ne pas utiliser Reachability si vous pouvez l'éviter, mais faites simplement l'appel et vérifiez le résultat. Avant l'appel, vous pouvez définir allowCellularAccess sur NO pour éviter les connections 3G coûteuses.

Évidemment, vous aurez des erreurs. Dans le cas particulier où la 3G était possible mais pas autorisée, et il n'y avait pas de WiFi, vous obtenez kCFURLErrorDataNotAllowed. Vous pouvez alors requestr à l'user s'il souhaite vous autoriser une connection 3G.

Sinon, vous obtiendrez kCFURLErrorNotConnectedToInternet s'il n'y a pas de connection Internet, et dans le cas spécial où il y aurait une connection 3G mais l'itinérance de données n'est pas autorisée (comme un téléphone américain dans un autre pays) vous obtiendrez kCFURLErrorInternationalRoamingOff. Il y a aussi kCFURLErrorCallIsActive que vous obtiendriez sur un téléphone qui ne peut pas utiliser la 3G pendant un appel.

Je l'ai fait pour vérifier l'itinérance (ce n'est pas une preuve complète à 100% mais ..):

1. D'abord, lorsque l'user charge l'application pour la première fois, enregistrez le réseau de l'opérateur dans les valeurs par défaut de l'user:

 CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init]; CTCarrier *carrier = [netinfo subscriberCellularProvider]; NSSsortingng *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. Chaque fois que vous avez besoin de vérifier le currentCarrier Vs celui que vous avez enregistré lors du premier lancement de l'application et si les noms sont différents, l'user est en itinérance.