I would like to check to see if I have an Internet connection on the iPhone using the Cocoa Touch libraries.
I came up with a way to do this using an NSUrl. The way I did it seems a bit unreliable (because even Google could one day be down and relying on a 3rd party seems bad) and while I could check to see for a response from some other websites if Google didn't respond, it does seem wasteful and an unnecessary overhead on my application.
- (BOOL) connectedToInternet
{
NSString *URLString = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.google.com"]];
return ( URLString != NULL ) ? YES : NO;
}
Is what I have done bad? (Not to mention 'stringWithContentsOfURL' is deprecated in 3.0) And if so what is a better way to accomplish this?
Source: Tips4all
Use a simple library to do it:
ReplyDeletehttps://github.com/tonymillion/Reachability (ARC and GCD Compatible Reachability)
OR... Do it yourself:
1) Add SystemConfiguration framework to the project but don't worry about including it anywhere
2) Add Reachability.h and Reachability.m to the project (you can get those here)
3) Add @class Reachability; to the .h file of where you are implementing the code
4) Create a couple instances to check in the interface section of the .h file:
Reachability* internetReachable;
Reachability* hostReachable;
5) Add a method in the .h for when the network status updates:
-(void) checkNetworkStatus:(NSNotification *)notice;
6) Add #import "Reachability.h" to the .m file where you are implementing the check
7) In the .m file of where you are implementing the check, you can place this in one of the first methods called (init or viewWillAppear or viewDidLoad etc):
-(void) viewWillAppear:(BOOL)animated
{
// check for internet connection
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
internetReachable = [[Reachability reachabilityForInternetConnection] retain];
[internetReachable startNotifier];
// check if a pathway to a random host exists
hostReachable = [[Reachability reachabilityWithHostName: @"www.apple.com"] retain];
[hostReachable startNotifier];
// now patiently wait for the notification
}
8) Set up the method for when the notification gets sent and set whatever checks or call whatever methods you may have set up (in my case, I just set a BOOL)
-(void) checkNetworkStatus:(NSNotification *)notice
{
// called after network status changes
NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
switch (internetStatus)
{
case NotReachable:
{
NSLog(@"The internet is down.");
self.internetActive = NO;
break;
}
case ReachableViaWiFi:
{
NSLog(@"The internet is working via WIFI.");
self.internetActive = YES;
break;
}
case ReachableViaWWAN:
{
NSLog(@"The internet is working via WWAN.");
self.internetActive = YES;
break;
}
}
NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
switch (hostStatus)
{
case NotReachable:
{
NSLog(@"A gateway to the host server is down.");
self.hostActive = NO;
break;
}
case ReachableViaWiFi:
{
NSLog(@"A gateway to the host server is working via WIFI.");
self.hostActive = YES;
break;
}
case ReachableViaWWAN:
{
NSLog(@"A gateway to the host server is working via WWAN.");
self.hostActive = YES;
break;
}
}
}
9) In your dealloc or viewWillDisappear or similar method, remove yourself as an observer
-(void) viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Note: There might be an instance using viewWillDisappear where you receive a memory warning and the observer never gets unregistered so you should account for that as well.
Edit: This used to be the correct answer, but is now outdated as you should subscribe to notifications for reachability instead. This methods checks synchronously:
ReplyDeleteYou can use Apple's Reachability class. It will also allow you to check if WiFi is enabled:
Reachability* reachability = [Reachability sharedReachability];
[reachability setHostName:@"www.example.com"]; // set your host name here
NetworkStatus remoteHostStatus = [reachability remoteHostStatus];
if(remoteHostStatus == NotReachable) { }
else if (remoteHostStatus == ReachableViaWiFiNetwork) { }
else if (remoteHostStatus == ReachableViaCarrierDataNetwork) { }
The Reachability class is not shipped with the SDK, but rather a part of this Apple sample application. Just download it and copy Reachability.h/m to your project. Also, you have to add the SystemConfiguration framework to your project.
I like to keep things simple. The way I do this is:
ReplyDelete//Class.h
#import "Reachability.h"
#import <SystemConfiguration/SystemConfiguration.h>
- (BOOL)connected ;
//Class.m
- (BOOL)connected
{
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [reachability currentReachabilityStatus];
return !(networkStatus == NotReachable);
}
Then, I use this whenever I wanna see if I have a connection:
if(![self connected])
{
// not connected
} else
{
// connected, do some internet stuff
}
This method doesn't wait for changed network statuses in order to do stuff, it just tests the status when you ask it to.
Using Apple's Reachability code I created a function that'll check this correctly without you having to include any classes.
ReplyDeleteInclude the SystemConfiguration.framework in your project.
Make some imports
#import <sys/socket.h>
#import <netinet/in.h>
#import <SystemConfiguration/SystemConfiguration.h>
Now just call this function
/*
Connectivity testing code pulled from Apple's Reachability Example: http://developer.apple.com/library/ios/#samplecode/Reachability
*/
+(BOOL)hasConnectivity {
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress);
if(reachability != NULL) {
//NetworkStatus retVal = NotReachable;
SCNetworkReachabilityFlags flags;
if (SCNetworkReachabilityGetFlags(reachability, &flags)) {
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
{
// if target host is not reachable
return NO;
}
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
{
// if target host is reachable and no connection is required
// then we'll assume (for now) that your on Wi-Fi
return YES;
}
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
{
// ... and the connection is on-demand (or on-traffic) if the
// calling application is using the CFSocketStream or higher APIs
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
{
// ... and no [user] intervention is needed
return YES;
}
}
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
{
// ... but WWAN connections are OK if the calling application
// is using the CFNetwork (CFSocketStream?) APIs.
return YES;
}
}
}
return NO;
}
And it's iOS5 tested for ya.
Apple supplies sample code to check for different types of network availability. Alternatively there is an example in the iPhone developers cookbook.
ReplyDeleteNote: Please see @KHG's comment on this answer regarding the use of Apple's reachability code.
Apple provides a sample app which does exactly this:
ReplyDeletehttp://developer.apple.com/iphone/library/samplecode/Reachability/index.html
Nice topic, a bit old but thanks anyway it helped me. Only the Reachability class has been updated. You can now use:
ReplyDeleteReachability* reachability = [Reachability reachabilityWithHostName:@"www.apple.com"];
NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus];
if(remoteHostStatus == NotReachable) { NSLog(@"not reachable");}
else if (remoteHostStatus == ReachableViaWWAN) { NSLog(@"reachable via wwan");}
else if (remoteHostStatus == ReachableViaWiFi) { NSLog(@"reachable via wifi");}
The type of check that you propose would not accomplish anything since the connection could be lost immediately after the check or during the subsequent operation. Instead, you should put code that requires an internet connection in separate threads (I recommend using NSOperation and/or NSInvocationOperation for this task). If the data is not received within a certain period of time, inform the user that a connection could not be established.
ReplyDeleteHere´s a version on Reachability for iOS 5, its not mine! =)
ReplyDeletehttps://gist.github.com/1182373
There's a nice-looking, ARC- and GCD-using modernization of Reachability here:
ReplyDeletehttps://github.com/tonymillion/Reachability
I've used the code in this discussion, and it seems to work fine (read the whole thread!).
ReplyDeleteI haven't tested it exhaustively with every conceivable kind of connection (like ad hoc wifi).
You could do:
ReplyDelete-(IBAction)NetworkCheck {
//Use this to "call" the check
UIWebView *networkChecker = [[UIWebView alloc] init];
[networkChecker loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com/"]]];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
NSString *checkError = [[error debugDescription] substringFromIndex:[[error debugDescription] length] -35];
if ([checkError isEqualToString:@"\"Could not connect to the server.\"}"]) {[self ShowErrorMessage];}
if ([checkError isEqualToString:@"Could not connect to the server.\"}"]) {[self ShowErrorMessage];}
if ([checkError isEqualToString:@"\"connection appears to be offline.\"}"]) {[self ShowErrorMessage];}
if ([checkError isEqualToString:@"connection appears to be offline.\"}"]) {[self ShowErrorMessage];}
}
Here's a very simple answer:
ReplyDeleteNSURL *scriptUrl = [NSURL URLWithString:@"http://apps.wegenerlabs.com/hi.html"];
NSData *data = [NSData dataWithContentsOfURL:scriptUrl];
if (data != nil)
NSLog(@"Device is connected to the internet");
else
NSLog(@"Device is not connected to the internet");
The URL points to an extremely small website that can be loaded fast in a cellular network. You are welcome to use my website, but you can also put a small file on your own website.
If checking whether the device is somehow connected to the internet is everything you want to do, I'd definitely recommend using this simple solution.
You have the reachability library, here made by apple just for this purpose.
ReplyDelete