7

Is there any way for me to detect whether or not a user is in the US without asking for their location? For example, when I go to Fandango on my computer it knows which county and state I'm in just based on my WiFi.

If I have a device, perhaps an iPod Touch, that doesn't have GPS, and I wanted to verify it is in the United States, and they are connected to WiFi... or if I had an iPhone and it was connected with 3G and I wanted to make sure the users were in the US, is there a way I can check that information without the little alert view "__ would like to use your current location"? I don't need exact coordinates, I just need to confirm that these users are in the USA (including Hawaii and Alaska)... locale?

Michal
  • 15,429
  • 10
  • 73
  • 104
Albert Renshaw
  • 17,282
  • 18
  • 107
  • 195
  • Right now I can detect "en_US" with the locale... Will this ALWAYS be the case in the United States? – Albert Renshaw Sep 06 '12 at 05:27
  • 2
    Locale is user configurable. For example, someone living in the United States who speaks Chinese might have their phone's language and locale set to China. You shouldn't use a user's locale to determine where they are located; it should be used to determine how to localize their content. – Scott Bartell Sep 11 '12 at 22:41

9 Answers9

7

Ok, how do you do that with the IP.

So, geoplugin.net has it's amazing JSON api, it defaults the IP to the currently conection, so what you have to do is make a request to this address:

http://www.geoplugin.net/json.gp

Astunishing! It returns, for me, this data:

geoPlugin({
  "geoplugin_request":"201.6.226.233",
  "geoplugin_status":200,
  "geoplugin_city":null,
  "geoplugin_region":"São Paulo",
  "geoplugin_areaCode":0,
  "geoplugin_dmaCode":0,
  "geoplugin_countryCode":"BR",
  "geoplugin_countryName":"Brazil",
  "geoplugin_continentCode":"SA",
  "geoplugin_latitude":-23.473301,
  "geoplugin_longitude":-46.665798,
  "geoplugin_regionCode":27,
  "geoplugin_regionName":"São Paulo",
  "geoplugin_currencyCode":"BRL",
  "geoplugin_currencySymbol":"R$",
  "geoplugin_currencyConverter":2.0198
})

Well, now what you have to do is just parse this "JSON". It's not actually a JSON as it has this geoplugin( {data} ) wrapper. So you could lazily execute some filtering, removing those parts of a NSSTring, maybe.

I See you are in a hurry, so I took my spare time to write some code for you. It's very non-standard as I don't know if you are using any REST framework that would help, but here goes:

NSString *url = [NSString stringWithFormat:@"http://www.geoplugin.net/json.gp"];


    NSString *locationData = [[NSString alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:url]]
                                                encoding:NSUTF8StringEncoding]];

    locationData = [locationData stringByReplacingOccurrencesOfString:@"geoPlugin(" withString:@""];
    locationData = [locationData stringByReplacingOccurrencesOfString:@")" withString:@""];

    //user some json parser here.
    if([[[locationData JSONValue] valueForkey:@"geoplugin_countryCode"] isEqualToString:@"US"]){

        //proceed.
    }
jturolla
  • 6,596
  • 7
  • 26
  • 41
5

I would first try to check the carrier's Mobile Country Code. It will tell you the numeric mobile country code for the user's cellular service provider and cannot be changed by the user unless they switch to a service provider in a different country.

#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreTelephony/CTCarrier.h>

CTTelephonyNetworkInfo *netInfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = [netInfo subscriberCellularProvider];
NSString *mcc = [carrier mobileCountryCode];

This of course will not work with devices that are not connected to a mobile carrier (iPod Touch, some iPads, ect). Therefor, as a fall back, I would use or create my own IP geolocation API. You can get a free database that is 99.5% accurate on a country level. This will work great to detect the country of a device that doesn't have a mobile provider.

Scott Bartell
  • 2,801
  • 3
  • 24
  • 36
  • This in combination with IP-location-matching as a fall back when carrier information is not available seems like a good solution. The carrier's Mobile Country Code would be a very accurate way to check for any cellular connected devices. Then when either carrier information is not available or a non-cellular device is being used you would fall back to the IP-location-matching. – Scott Lemmon Sep 11 '12 at 23:51
  • 1
    One question about the MCC: when out of the country roaming, is the MCC that is provided the base carrier's, or the roaming carrier's MCC? – Scott Lemmon Sep 11 '12 at 23:56
  • 4
    @ScottLemmon from [apple's documentation](http://developer.apple.com/library/ios/DOCUMENTATION/NetworkingInternet/Reference/CTCarrier/Reference/Reference.html#//apple_ref/doc/uid/TP40009596-CH1-SW1) - "The value does not change if the user is roaming; it always represents the provider with whom the user has an account." – Scott Bartell Sep 12 '12 at 06:53
  • 1
    By far the best solution (in combination with my IP address code I mentioned below! in the first answer to this question!) – Albert Renshaw Sep 14 '12 at 05:20
  • +1 for the interesting hint. But it does not answer the question for location of the user but fot location of the user's home carrier, if I understand MCC/MNC correctly! – I'm with Monica Sep 14 '12 at 05:44
3

In a networked environment the user's location is usually "identified" through the IP address.

What is the purpose of the inside/outside US determination? How accurate/fail safe has it to be? What are the consequences, when a user is wrongly identified as being inside the US? What are the consequences, when you produce a false negative? Are you violating contracts or licenses, when you have a false positive? Or even commiting a crime? Or do you just dislike foreigners and it is your (or your employer's) dignity that is injured?

The real question is: How reliable is the information you gain by localizing an IP address and is this reliability enough for your purpose?

As you have a way to get a country code for a given IP address, you just have to compare it to the given set of allowed codes and you are done. If, that is, the quality of the source of said code meets your requirements.

I'm with Monica
  • 328
  • 8
  • 19
  • It has to be very accurate and I'm under NDA for the purpose of it. If I have the IP Address via WiFi I can detect the users city and country, if I just have the IP address via 3g I should still be able to check the users country right? I tried doing research and apparently there are ways to check the country of an IP address but they involve finding the ip address, converting it from an address to an ip number, then checking one last thing which I can't seem to find... – Albert Renshaw Sep 06 '12 at 15:20
  • Okay I was able to find a service (api.ipinfodb.com) that produces a JSON of the IP Info.. so if my JSON returns a string that has all of this stuff: { "statusCode" : "OK", "statusMessage" : "", "ipAddress" : "************", "countryCode" : "US", "countryName" : "UNITED STATES" } and I just want to check that the country code says US, UM or VI how do I do that? – Albert Renshaw Sep 06 '12 at 15:39
  • Sorry for my late response, the weekend hit me too early. So you have the country code (I presume as a two letter ISO 3166-1 alpha-2 code) for a given IP address. You just have to compare it to the given set of allowed codes and you are done, if I understand your requirements correctly?! – I'm with Monica Sep 10 '12 at 05:59
  • And a given set would be..? Haha.. oh boy, this is a long one... I found one online but it cost me $50! Haha, still testing it, not sure if it's 100% accurate. – Albert Renshaw Sep 11 '12 at 03:22
  • I had to grab the IP address via PHP from my own server as well – Albert Renshaw Sep 11 '12 at 03:22
  • Oh and by the way to answer your question about the "U.S." only, in the app users will be submitting data for an event that is U.S. only and anyone outside the U.S. submitting data would tamper with the validity of our results, so in order to maintain reliable results our clients would like "U.S. only" submitters. – Albert Renshaw Sep 11 '12 at 03:24
  • You cannot be absolutely sure, I'm afraid, of the validity of the IP-location-matching. You would have to control the network for that. - But with the alpha-2 code you could just check for "US", "VI" and "UM" and just accept that there is a slight chance to block legitimate users accessing your service via an address listed as outside the US and allowing illegitimate ones from outside the US. It is, not at least, only relevant, if those few users even try to use your service. – I'm with Monica Sep 11 '12 at 05:55
1

The simplest solution is to query an existing web service, like hostip.info.

Please note that this is merely a sample (you should query the web service differently), but for the sake of simplicity:

NSError* error = nil;
NSString* country = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://api.hostip.info/country.php"] encoding:NSUTF8StringEncoding error:&error];
//will show US if user is in the United States
NSLog(@"%@", country);

You'd also acquire a (free) database yourself from http://www.maxmind.com/app/installation and either create a web service or include it in your application (not recommended.)

martijndeh
  • 361
  • 3
  • 11
1

have alook at geoPlugin, it has several webservices you can use to get the users location based of the IP and its free.

Rayvyn
  • 77
  • 1
  • 7
0

If you are not allowed to ask for the user's location, using an IP based reverse geolocation service is the only way to go. I've never used any public services so I can't comment on the quality of any of them, unfortunately. This can be inaccurate as far as regions within the USA (I've seen IPs from 3G connections be way off). This will probably defeat the casual user.

Of course, sophisticated 'attackers' will get around this easily with a proxy. There seem to be ways of detecting if requests come from proxies but these don't seem to be 100% either.

If using the user's location becomes an option, then you can use either CLGeocoder, or use a web service that does reverse geocoding from latitude and longitude values collected via Core Location. For an even greater level of security, sign the latitude and longitude values to help ensure their integrity. I think that's probably the best option if you really need to have the best possible protection from international users participating.

Hopefully this helps put you on the right track. There are a lot of options out there so I'm confident depending on your needs you'll be able to find a good solution.

Community
  • 1
  • 1
Carl Veazey
  • 18,392
  • 8
  • 66
  • 81
0

if you want to reach information about your current city - country etc. with your current location info (latitude, longitude) you can use this

hope works for you. good luck.

EDİT:

ohh sorry, i didnt see the info about GPS.

relower
  • 1,293
  • 1
  • 10
  • 20
0

You will easily find the database on the web that will tell you about user country based on their IP then make a web-service that will detect the user IP and return the flag for US.

Asad Nauman
  • 971
  • 11
  • 19
0

You said you can't ask the user for the location. Are you able to use CoreLocation for location services? If you are, then you are very likely going to be able to obtain their location without asking them, simply by using location services. GPS is not required, as long as wifi is enabled. There are several good points about this made in this thread.

Once you have obtained the location, you can use a geocoder to determine if it's located in the US.

If you need more details, just ask, but this method is really very simple.

Community
  • 1
  • 1
Jim
  • 5,940
  • 9
  • 44
  • 91