2009-05-30 5 views
1

인터넷 연결을 사용할 수있는 경우 웹에서 내 앱 다운로드 정보 화면을 만드는 방법을 찾으려고합니다. 따라서 정기적으로 업데이트 할 수 있습니다. 인터넷을 사용할 수없는 경우 기본값 또는 마지막으로 다운로드 한 것을 사용해야합니다. 이것이 가능한가?동적 정보 화면

답변

2

위의 James Skitmore가 제공하는 방법은 연결 테스트를위한 끔찍한 방법입니다. 하시기 바랍니다아니 그것을 사용하십시오. 불필요하게 google.com을로드하면 네트워크가 사용 가능하지 않으면 시간 초과가 발생하여 앱이 정지 된 것처럼 보입니다.

다음은 인터넷 연결을 확인하는 방법입니다.

if (![[UIDevice currentDevice] networkAvailable]) 

당신은 지금 또한 yourwebsite.com로, 특정 호스트에 연결을 확인하거나, 확인 수 : 앱에

, 당신은 네트워크를 사용할 수 있는지 여부를 확인하기 위해이 작업을 수행 할 수 있습니다 3G 형 대 Wifi 형 등이 있습니다. 헤더 파일을 읽음으로써 이것을 직접 이해할 수 있습니다.

/* 
Erica Sadun, http://ericasadun.com 
iPhone Developer's Cookbook, 3.0 Edition 
BSD License for anything not specifically marked as developed by a third party. 
Zach Waugh and Apple's code excluded. 
Use at your own risk 
*/ 

#import <UIKit/UIKit.h> 

#define SUPPORTS_UNDOCUMENTED_API 1 

@interface UIDevice (Reachability) 
- (NSString *) hostname; 

- (NSString *) localWiFiIPAddress; 
- (NSString *) localIPAddress; 
- (NSString *) whatismyipdotcom; 

- (BOOL) activeWLAN; 
- (BOOL) addressFromString:(NSString *)IPAddress address:(struct sockaddr_in *)address; // via Apple 
- (void) forceWWAN; // via Apple 
- (void) shutdownWWAN; // via Apple 
@end 

// Methods which rely on undocumented API methods 
#if SUPPORTS_UNDOCUMENTED_API 

@interface UIDevice (UIDevice_Undocumented_Reachability) 
- (BOOL) networkAvailable; 
- (BOOL) activeWWAN; 
@end 

#endif // SUPPORTS_UNDOCUMENTED_API 

UIDevice-Reachability.m

을 (에리카 Sadun의 제공)

UIDevice-Reachability.h :

당신은 당신의 응용 프로그램에 다음 파일을 포함 할 필요 해요

/* 
Erica Sadun, http://ericasadun.com 
iPhone Developer's Cookbook, 3.0 Edition 
BSD License for anything not specifically marked as developed by a third party. 
Apple's code excluded. 
Use at your own risk 
*/ 

// TTD: Add async version of whatsmyip -- thanks rpetrich 

#include <unistd.h> 
#include <sys/sysctl.h> 
#include <arpa/inet.h> 
#include <netdb.h> 
#include <net/if.h> 
#include <net/if_dl.h> 
#include <netinet/in.h> 
#include <ifaddrs.h> 

#import "UIDevice-Reachability.h" 
#import "wwanconnect.h" 

@implementation UIDevice (Reachability) 

#pragma mark host and ip utils 
- (NSString *) hostname 
{ 
    char baseHostName[255]; 
    int success = gethostname(baseHostName, 255); 
    if (success != 0) return nil; 
    baseHostName[255] = '\0'; 

#if !TARGET_IPHONE_SIMULATOR 
    return [NSString stringWithFormat:@"%s.local", baseHostName]; 
#else 
    return [NSString stringWithFormat:@"%s", baseHostName]; 
#endif 
} 

// Direct from Apple. Thank you Apple 
- (BOOL)addressFromString:(NSString *)IPAddress address:(struct sockaddr_in *)address 
{ 
    if (!IPAddress || ![IPAddress length]) { 
     return NO; 
    } 

    memset((char *) address, sizeof(struct sockaddr_in), 0); 
    address->sin_family = AF_INET; 
    address->sin_len = sizeof(struct sockaddr_in); 

    int conversionResult = inet_aton([IPAddress UTF8String], &address->sin_addr); 
    if (conversionResult == 0) { 
     NSAssert1(conversionResult != 1, @"Failed to convert the IP address string into a sockaddr_in: %@", IPAddress); 
     return NO; 
    } 

    return YES; 
} 

- (NSString *) getIPAddressForHost: (NSString *) theHost 
{ 
    struct hostent *host = gethostbyname([theHost UTF8String]); 

    if (host == NULL) { 
     herror("resolv"); 
     return NULL; 
    } 

    struct in_addr **list = (struct in_addr **)host->h_addr_list; 
    NSString *addressString = [NSString stringWithCString:inet_ntoa(*list[0])]; 
    return addressString; 
} 

#if ! defined(IFT_ETHER) 
#define IFT_ETHER 0x6 // Ethernet CSMACD 
#endif 

// Matt Brown's get WiFi IP addy solution 
// Author gave permission to use in Cookbook under cookbook license 
// http://mattbsoftware.blogspot.com/2009/04/how-to-get-ip-address-of-iphone-os-v221.html 
- (NSString *) localWiFiIPAddress 
{ 
    BOOL success; 
    struct ifaddrs * addrs; 
    const struct ifaddrs * cursor; 

    success = getifaddrs(&addrs) == 0; 
    if (success) { 
     cursor = addrs; 
     while (cursor != NULL) { 
      // the second test keeps from picking up the loopback address 
      if (cursor->ifa_addr->sa_family == AF_INET && (cursor->ifa_flags & IFF_LOOPBACK) == 0) 
      { 
       NSString *name = [NSString stringWithUTF8String:cursor->ifa_name]; 
       if ([name isEqualToString:@"en0"]) { // found the WiFi adapter 
        return [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)cursor->ifa_addr)->sin_addr)]; 
       } 
      } 
      cursor = cursor->ifa_next; 
     } 
     freeifaddrs(addrs); 
    } 
    return nil; 
} 

// Return the local IP address 
- (NSString *) localIPAddress 
{ 
    struct hostent *host = gethostbyname([[self hostname] UTF8String]); 
    if (host == NULL) 
    { 
     herror("resolv"); 
     return nil; 
    } 
    else { 
     struct in_addr **list = (struct in_addr **)host->h_addr_list; 
     return [NSString stringWithCString:inet_ntoa(*list[0])]; 
    } 
    return nil; 
} 

- (NSString *) whatismyipdotcom 
{ 
    NSError *error; 
    NSURL *ipURL = [NSURL URLWithString:@"http://www.whatismyip.com/automation/n09230945.asp"]; 
    NSString *ip = [NSString stringWithContentsOfURL:ipURL encoding:1 error:&error]; 
    if (!ip) return [error localizedDescription]; 
    return ip; 
} 

- (BOOL) activeWLAN 
{ 
    return ([self localWiFiIPAddress] != nil); 
} 

#pragma mark Forcing WWAN connection 

MyStreamInfoPtr myInfoPtr; 

static void myClientCallback(void *refCon) 
{ 
    int *val = (int*)refCon; 
    printf("myClientCallback entered - value from refCon is %d\n", *val); 
} 

- (void) forceWWAN 
{ 
    int value = 0; 
    myInfoPtr = (MyStreamInfoPtr) StartWWAN(myClientCallback, &value); 
    if (myInfoPtr) 
    { 
     printf("Started WWAN\n"); 
    } 
    else 
    { 
     printf("Failed to start WWAN\n"); 
    } 
} 

- (void) shutdownWWAN 
{ 
    if (myInfoPtr) StopWWAN((MyInfoRef) myInfoPtr); 
} 
@end 

#if SUPPORTS_UNDOCUMENTED_API 
@implementation UIDevice (UIDevice_Undocumented_Reachability) 
- (BOOL) networkAvailable 
{ 
    // Unavailable has only one address: 127.0.0.1 
    return !(([[[NSHost currentHost] addresses] count] == 1) && [[self localIPAddress] isEqualToString:@"127.0.0.1"]); 
} 

- (BOOL) activeWWAN 
{ 
    return ([self networkAvailable] && ![self localWiFiIPAddress]); 
} 
@end 
#endif // SUPPORTS_UNDOCUMENTED_API 

wwanconnect.h

// Direct from Apple. Thank you Apple 

#if !defined(__WWAN_CONNECT__) 
#define __WWAN_CONNECT__ 1 

#include <CoreFoundation/CoreFoundation.h> 
#include <assert.h> 

#define kTestHost "www.whatismyip.com" 
#define kTestPort 80  

typedef void (*ConnectClientCallBack)(void *refCon); 


struct MyStreamInfoStruct{ 
    CFWriteStreamRef  wStreamRef; 
    CFReadStreamRef   rStreamRef; 
    ConnectClientCallBack clientCB; 
    void     *refCon; 
    CFStreamError   error; 
    Boolean     errorOccurred; 
    Boolean     isConnected; 
    Boolean     isStreamInitd; 
    Boolean     isClientSet; 
}; 

typedef struct MyStreamInfoStruct MyStreamInfo; 
typedef struct MyStreamInfoStruct *MyStreamInfoPtr; 
typedef struct __MyInfoRef *MyInfoRef; 

/* 
* StartWWAN() 
* 
* Discussion: 
* This function will initiate a Wireless Wide Area Network (WWAN) 
*  connection by using the CFSocketStream API to connect with a 
*  server system defined by kTestHost:kTestPort above. 
*  No communications are expected to happen over the CFSocketStream 
*  connection. 
* 
* clientCB: 
*  if the connection is opened, the callback routine, if not NULL 
*  will be called. function defintion - see ConnectClientCallBack above 
*  
* refCon: 
*  if a client callback, clientCB is defined, then the refCon 
*  parameter will be the argument to the client callback 
* 
* return: 
*  if the WWAN connection is successful, a MyInfoRef value is returned 
*  The MyInfoRef value must be passed to StopWWAN to stop the WWAN 
*  connection. 
*  A NULL result indicates that the connection was unsuccessful 
*  
*/ 
extern MyInfoRef StartWWAN(ConnectClientCallBack clientCB, void *refCon); 

/* 
* StopWWAN() 
* 
* Discussion: 
* This function closes the CFSocketStream which was used to establish the 
* WWAN connection. Once the WWAN connection has been started, BSD 
* network functions can be used to communicate across the WWAN connection. 
* As of the writing of this sample, there is no guarantee that the use of 
* only BSD socket API's will maintain the WWAN connection. 
* 
* infoRef: 
*  pass in the MyInfoRef result from the StartWWAN function. 
*  
*/ 

extern void StopWWAN(MyInfoRef infoRef); 

#endif // __WWAN_CONNECT__ 

wwanconnect.c

// Direct from Apple. Thank you Apple 

#include "wwanconnect.h" 
#include <CFNetwork/CFSocketStream.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <ifaddrs.h> 
#include <stdio.h> 

static Boolean TestGetIFAddrs(void); 
static void MyCFWriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType type, void *clientCallBackInfo); 
static void CleanupAfterWAAN(MyStreamInfoPtr myInfoPtr); 
static void CloseStreams(MyStreamInfoPtr myInfoPtr); 

static Boolean TestGetIFAddrs(void) 
{ 
    int    result; 
    struct ifaddrs *ifbase, *ifiterator; 
    int    done = 0; 
    Boolean   addrFound = FALSE; 
    char   loopbackname[] = "lo0/0"; 

    result = getifaddrs(&ifbase); 
    ifiterator = ifbase; 
    while (!done && (ifiterator != NULL)) 
    { 
     if (ifiterator->ifa_addr->sa_family == AF_INET) 
     { 
      if (memcmp(ifiterator->ifa_name, loopbackname, 3)) 
      { 
       struct sockaddr *saddr, *netmask, *daddr; 
       saddr = ifiterator->ifa_addr; 
       netmask = ifiterator->ifa_netmask; 
       daddr = ifiterator->ifa_dstaddr; 

       // we've found an entry for the IP address 
       struct sockaddr_in *iaddr; 
       char    addrstr[64]; 
       iaddr = (struct sockaddr_in *)saddr; 
       inet_ntop(saddr->sa_family, &iaddr->sin_addr, addrstr, sizeof(addrstr)); 
       fprintf(stderr, "ipv4 interface name %s, source IP addr %s ", ifiterator->ifa_name, addrstr); 

       iaddr = (struct sockaddr_in *)netmask; 
       if (iaddr) 
       { 
        inet_ntop(saddr->sa_family, &iaddr->sin_addr, addrstr, sizeof(addrstr)); 
        fprintf(stderr, "netmask IP addr %s ", addrstr); 
       } 

       iaddr = (struct sockaddr_in *)daddr; 
       if (iaddr) 
       { 
        inet_ntop(saddr->sa_family, &iaddr->sin_addr, addrstr, sizeof(addrstr)); 
        fprintf(stderr, "dest/broadcast IP addr %s.\n\n", addrstr); 
       } 
       return TRUE; 
      } 

     } 
     else if (ifiterator->ifa_addr->sa_family == AF_INET6) 
     { 
      // we've found an entry for the IP address 
      struct sockaddr_in6 *iaddr6 = (struct sockaddr_in6 *)ifiterator->ifa_addr; 
      char    addrstr[256]; 
      inet_ntop(ifiterator->ifa_addr->sa_family, iaddr6, addrstr, sizeof(addrstr)); 
      fprintf(stderr, "ipv6 interface name %s, source IP addr %s \n\n", ifiterator->ifa_name, addrstr); 
     } 
     ifiterator = ifiterator->ifa_next; 
    } 
    if (ifbase) 
     freeifaddrs(ifbase); /* done with the memory allocated by getifaddrs */ 

    return addrFound; 
} 

static void MyCFWriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType type, void *clientCallBackInfo) 
{ 
    MyStreamInfoPtr myInfoPtr = (MyStreamInfoPtr) clientCallBackInfo; 

    printf("MyCFWriteStreamClientCallBack entered - event is %d\n", type); 

    switch (type) 
    { 
     case kCFStreamEventOpenCompleted: 
      myInfoPtr->isConnected = TRUE; 
      TestGetIFAddrs();  // call the test function to return the local ip address associated with this connection. 
      if (myInfoPtr->clientCB) 
      { 
       // call client callback routine 
       myInfoPtr->clientCB(myInfoPtr->refCon); 
      } 
      printf("write stream connected\n"); 
      break; 

     case kCFStreamEventErrorOccurred: 
      myInfoPtr->errorOccurred = TRUE; 
      myInfoPtr->error = CFWriteStreamGetError(myInfoPtr->wStreamRef); 
      printf("write stream error %d .. giving up\n", myInfoPtr->error.error); 
      break; 

     default: 
      printf("event type %d occurred\n"); 
      break; 
    } 
    // stop the run loop at this point 
    CFRunLoopStop(CFRunLoopGetCurrent()); 
} 

extern MyInfoRef StartWWAN(ConnectClientCallBack clientCB, void *refCon) 
{ 
    char      host[] = kTestHost; 
    int       portNum = kTestPort; 
    CFDataRef     addressData; 
    MyStreamInfoPtr    myInfoPtr; 
    CFStreamClientContext  ctxt = {0, NULL, NULL, NULL, NULL}; 
    Boolean      errorOccurred = FALSE; 

    myInfoPtr = malloc(sizeof(MyStreamInfo)); 
    if (!myInfoPtr) 
    { 
     return NULL; 
    } 

    // init the allocated memory 
    memset(myInfoPtr, 0, sizeof(MyStreamInfo)); 
    myInfoPtr->clientCB = clientCB; 
    myInfoPtr->refCon = refCon; 
    ctxt.info = myInfoPtr; 

    // Check for a dotted-quad address, if so skip any host lookups 
    in_addr_t addr = inet_addr(host); 
    if (addr != INADDR_NONE) { 
     // Create the streams from numberical host 
     struct sockaddr_in sin; 
     memset(&sin, 0, sizeof(sin)); 

     sin.sin_len= sizeof(sin); 
     sin.sin_family = AF_INET; 
     sin.sin_addr.s_addr = addr; 
     sin.sin_port = htons(portNum); 

     addressData = CFDataCreate(NULL, (UInt8 *)&sin, sizeof(sin)); 
     CFSocketSignature sig = { AF_INET, SOCK_STREAM, IPPROTO_TCP, addressData }; 

     // Create the streams. 
     CFStreamCreatePairWithPeerSocketSignature(kCFAllocatorDefault, &sig, &(myInfoPtr->rStreamRef), &(myInfoPtr->wStreamRef));  
     CFRelease(addressData); 
    } else { 
     // Create the streams from ascii host name 
     CFStringRef hostStr = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, host, kCFStringEncodingUTF8, kCFAllocatorNull); 
     CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, hostStr, portNum, &(myInfoPtr->rStreamRef), &(myInfoPtr->wStreamRef)); 
    } 

    myInfoPtr->isConnected = FALSE; 
    myInfoPtr->isStreamInitd = TRUE; 
    myInfoPtr->isClientSet = FALSE; 

    // Inform the streams to kill the socket when it is done with it. 
    // This effects the write stream too since the pair shares the 
    // one socket. 
    CFWriteStreamSetProperty(myInfoPtr->wStreamRef, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); 

    // set up the client 
    if (!CFWriteStreamSetClient(myInfoPtr->wStreamRef, kCFStreamEventOpenCompleted | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, 
           MyCFWriteStreamClientCallBack, &ctxt)) 
    { 
     printf("CFWriteStreamSetClient failed\n"); 
     errorOccurred = TRUE; 
    } 
    else 
     myInfoPtr->isClientSet = TRUE; 

    if (!errorOccurred) 
    { 
     // schedule the stream 
     CFWriteStreamScheduleWithRunLoop(myInfoPtr->wStreamRef, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); 

     // Try to open the stream. 
     if (!CFWriteStreamOpen(myInfoPtr->wStreamRef)) 
     { 
      printf("CFWriteStreamOpen failed\n"); 
      errorOccurred = TRUE; 
     } 
    } 

    if (!errorOccurred) 
    { 
     // everything worked so far, so run the runloop - when the callback gets called, it will stop the run loop 
     printf("CFWriteStreamOpen returned with no error - calling CFRunLoopRun\n"); 
     CFRunLoopRun(); 
     if (myInfoPtr->errorOccurred) 
      errorOccurred = TRUE; 
     printf("after CFRunLoopRun - returning\n"); 
    } 

    if (errorOccurred) 
    { 
     myInfoPtr->isConnected = FALSE; 
     CleanupAfterWAAN(myInfoPtr); 
     CloseStreams(myInfoPtr); 

     if (myInfoPtr->isStreamInitd) 
     { 
      CFRelease(myInfoPtr->rStreamRef); 
      CFRelease(myInfoPtr->wStreamRef); 
      myInfoPtr->isStreamInitd = FALSE; 
     } 
     free(myInfoPtr); 
     return NULL; 
    } 
    return (MyInfoRef)myInfoPtr; 
} 

static void CleanupAfterWAAN(MyStreamInfoPtr myInfoPtr) 
{ 
    assert(myInfoPtr != NULL); 
    if (myInfoPtr->isClientSet) 
    { 
     CFWriteStreamSetClient(myInfoPtr->wStreamRef, 0, NULL, NULL); 
     CFWriteStreamUnscheduleFromRunLoop(myInfoPtr->wStreamRef, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); 
     myInfoPtr->isClientSet = FALSE; 
    } 
} 

static void CloseStreams(MyStreamInfoPtr myInfoPtr) 
{ 
    assert(myInfoPtr != NULL); 
    if (myInfoPtr->rStreamRef) 
    { 
     CFReadStreamClose(myInfoPtr->rStreamRef); 
     myInfoPtr->rStreamRef = NULL; 
    } 
    if (myInfoPtr->wStreamRef) 
    { 
     CFWriteStreamClose(myInfoPtr->wStreamRef); 
     myInfoPtr->wStreamRef = NULL; 
    } 
} 

extern void StopWWAN(MyInfoRef infoRef) 
{ 
    MyStreamInfoPtr myInfoPtr = (MyStreamInfoPtr)infoRef; 

    printf("stopWWAN entered\n"); 
    assert(myInfoPtr != NULL); 
    myInfoPtr->isConnected = FALSE; 
    CleanupAfterWAAN(myInfoPtr); 
    CloseStreams(myInfoPtr); 
    free(myInfoPtr); 
} 
관련 문제