Determine internet connection

This commit is contained in:
Christoph Wendt 2015-09-03 23:17:31 -07:00
parent 64cee4dc80
commit 6f179eaced
3 changed files with 371 additions and 0 deletions

134
Classes/BITReachability.h Normal file
View File

@ -0,0 +1,134 @@
#import <Foundation/Foundation.h>
#import "HockeySDKPrivate.h"
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#endif
NS_ASSUME_NONNULL_BEGIN
/**
* Enum for representing different network statuses.
*/
typedef NS_ENUM(NSInteger, BITReachabilityType){
/**
* Type used if no connection is available.
*/
BITReachabilityTypeNone,
/**
* Type used for WiFi connnection.
*/
BITReachabilityTypeWIFI,
/**
* Type for Edge, 3G, LTE etc.
*/
BITReachabilityTypeWWAN,
BITReachabilityTypeGPRS,
BITReachabilityTypeEDGE,
BITReachabilityType3G,
BITReachabilityTypeLTE
};
FOUNDATION_EXPORT NSString* const kBITReachabilityTypeChangedNotification;
FOUNDATION_EXPORT NSString* const kBITReachabilityUserInfoName;
FOUNDATION_EXPORT NSString* const kBITReachabilityUserInfoType;
/**
* The BITReachability class is responsible for keep track of the network status currently used.
* Some customers need to send data only via WiFi. The network status is part of the context fields
* of an envelop object.
*/
@interface BITReachability : NSObject
///-----------------------------------------------------------------------------
/// @name Initialization
///-----------------------------------------------------------------------------
/**
* A queue to make calls to the singleton thread safe.
*/
@property (nonatomic, strong) dispatch_queue_t singletonQueue;
/**
* Returns a shared BITReachability object
*
* @return singleton instance.
*/
+ (instancetype)sharedInstance;
///-----------------------------------------------------------------------------
/// @name Register for network changes
///-----------------------------------------------------------------------------
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0
/**
* Object to determine current radio type.
*/
@property (nonatomic, strong) CTTelephonyNetworkInfo *radioInfo;
#endif
/**
* A queue for dispatching reachability operations.
*/
@property (nonatomic, strong) dispatch_queue_t networkQueue;
/**
* Register for network status notifications.
*/
- (void)startNetworkStatusTracking;
/**
* Unregister for network status notifications.
*/
- (void)stopNetworkStatusTracking;
///-----------------------------------------------------------------------------
/// @name Broadcast network changes
///-----------------------------------------------------------------------------
/**
* Updates and broadcasts network changes.
*/
- (void)notify;
///-----------------------------------------------------------------------------
/// @name Get network status
///-----------------------------------------------------------------------------
/**
* Get the current network type.
*
* @return the connection type currently used.
*/
- (BITReachabilityType)activeReachabilityType;
/**
* Get the current network type name.
*
* @return a human readable name for the current reachability type.
*/
- (NSString *)descriptionForActiveReachabilityType;
///-----------------------------------------------------------------------------
/// @name Helper
///-----------------------------------------------------------------------------
/**
* Returns a BITReachabilityType for a given radio technology name.
*
* @param technology name of the active radio technology
*
* @return reachability Type, which expresses the WWAN connection
*/
- (BITReachabilityType)wwanTypeForRadioAccessTechnology:(NSString *)technology;
/**
* Returns a human readable name for a given BITReachabilityType.
*
* @param reachabilityType the reachability type to convert.
*
* @return a human readable type name
*/
- (NSString *)descriptionForReachabilityType:(BITReachabilityType)reachabilityType;
@end
NS_ASSUME_NONNULL_END

227
Classes/BITReachability.m Normal file
View File

@ -0,0 +1,227 @@
#import "BITReachability.h"
#import <CoreFoundation/CoreFoundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <sys/socket.h>
NSString * const kBITReachabilityTypeChangedNotification = @"BITReachabilityTypeChangedNotification";
NSString* const kBITReachabilityUserInfoName = @"kName";
NSString* const kBITReachabilityUserInfoType = @"kType";
static char *const BITReachabilitySingletonQueue = "com.microsoft.ApplicationInsights.singletonQueue";
static char *const BITReacabilityNetworkQueue = "com.microsoft.ApplicationInsights.networkQueue";
static void BITReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info){
if(info != NULL && [(__bridge NSObject*) info isKindOfClass: [BITReachability class]]){
[(__bridge BITReachability *)info notify];
}
}
@implementation BITReachability{
SCNetworkReachabilityRef _reachability;
BITReachabilityType _reachabilityType;
BOOL _running;
}
#pragma mark - Initialize & configure shared instance
+ (instancetype)sharedInstance {
static BITReachability *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [BITReachability new];
sharedInstance.singletonQueue = dispatch_queue_create(BITReachabilitySingletonQueue, DISPATCH_QUEUE_SERIAL);
sharedInstance.networkQueue = dispatch_queue_create(BITReacabilityNetworkQueue, DISPATCH_QUEUE_SERIAL);
if ([CTTelephonyNetworkInfo class]) {
sharedInstance.radioInfo = [CTTelephonyNetworkInfo new];
}
[sharedInstance configureReachability];
});
return sharedInstance;
}
- (void)registerRadioObserver{
__weak typeof(self) weakSelf = self;
[NSNotificationCenter.defaultCenter addObserverForName:CTRadioAccessTechnologyDidChangeNotification
object:nil
queue:nil
usingBlock:^(NSNotification *note)
{
typeof(self) strongSelf = weakSelf;
[strongSelf notify];
}];
}
- (void)unregisterRadioObserver{
[NSNotificationCenter.defaultCenter removeObserver:self name:CTRadioAccessTechnologyDidChangeNotification object:nil];
}
- (void)configureReachability{
__weak typeof(self) weakSelf = self;
dispatch_sync(self.singletonQueue, ^{
typeof(self) strongSelf = weakSelf;
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
SCNetworkReachabilityRef networkReachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress);
if (networkReachability != NULL){
strongSelf->_reachability = networkReachability;
}
});
}
#pragma mark - Register for network changes
- (void)startNetworkStatusTracking{
__weak typeof(self) weakSelf = self;
dispatch_async(self.singletonQueue, ^{
typeof(self) strongSelf = weakSelf;
if(_running){
return;
}
SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
context.info = (__bridge void *)self;
if(SCNetworkReachabilitySetCallback(strongSelf->_reachability, BITReachabilityCallback, &context)){
if(SCNetworkReachabilitySetDispatchQueue(strongSelf->_reachability, strongSelf.networkQueue)){
if ([CTTelephonyNetworkInfo class]) {
[strongSelf registerRadioObserver];
}
strongSelf->_running = YES;
}else{
SCNetworkReachabilitySetCallback(strongSelf->_reachability, NULL, NULL);
}
}
});
}
- (void)stopNetworkStatusTracking{
__weak typeof(self) weakSelf = self;
dispatch_async(self.singletonQueue, ^{
typeof(self) strongSelf = weakSelf;
if ([CTTelephonyNetworkInfo class]) {
[strongSelf unregisterRadioObserver];
}
if (strongSelf->_reachability != NULL){
SCNetworkReachabilitySetCallback(strongSelf->_reachability, NULL, NULL);
SCNetworkReachabilitySetDispatchQueue(strongSelf->_reachability, NULL);
_running = NO;
}
});
}
#pragma mark - Broadcast network changes
- (void)notify{
__weak typeof(self) weakSelf = self;
dispatch_async(self.singletonQueue, ^{
typeof(self) strongSelf = weakSelf;
_reachabilityType = [strongSelf activeReachabilityType];
NSDictionary *notificationDict = @{kBITReachabilityUserInfoName:[strongSelf descriptionForReachabilityType:strongSelf->_reachabilityType],
kBITReachabilityUserInfoType:@(strongSelf->_reachabilityType)};
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:kBITReachabilityTypeChangedNotification object:nil userInfo:notificationDict];
});
});
}
#pragma mark - Get network status
- (BITReachabilityType)activeReachabilityType{
BITReachabilityType reachabilityType = BITReachabilityTypeNone;
SCNetworkReachabilityFlags flags;
if(SCNetworkReachabilityGetFlags(_reachability, &flags)){
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0){
return BITReachabilityTypeNone;
}
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0){
reachabilityType = BITReachabilityTypeWIFI;
}
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)){
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0){
reachabilityType = BITReachabilityTypeWIFI;
}
}
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN){
reachabilityType = BITReachabilityTypeWWAN;
// TODO: Radio info is nil after app returns to foreground, so set reachability type to wwan for now
if ([CTTelephonyNetworkInfo class] && self.radioInfo && self.radioInfo.currentRadioAccessTechnology) {
reachabilityType = [self wwanTypeForRadioAccessTechnology:self.radioInfo.currentRadioAccessTechnology];
}
}
}
return reachabilityType;
}
- (NSString *)descriptionForActiveReachabilityType{
BITReachabilityType currentType = [self activeReachabilityType];
return [self descriptionForReachabilityType:currentType];
}
#pragma mark - Helper
- (BITReachabilityType)wwanTypeForRadioAccessTechnology:(NSString *)technology{
BITReachabilityType radioType = BITReachabilityTypeNone;
// TODO: Check mapping
if([technology isEqualToString:CTRadioAccessTechnologyGPRS]||
[technology isEqualToString:CTRadioAccessTechnologyCDMA1x]){
radioType = BITReachabilityTypeGPRS;
}else if([technology isEqualToString:CTRadioAccessTechnologyEdge]){
radioType = BITReachabilityTypeEDGE;
}else if([technology isEqualToString:CTRadioAccessTechnologyWCDMA]||
[technology isEqualToString:CTRadioAccessTechnologyHSDPA]||
[technology isEqualToString:CTRadioAccessTechnologyHSUPA]||
[technology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0]||
[technology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA]||
[technology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB]||
[technology isEqualToString:CTRadioAccessTechnologyeHRPD]){
radioType = BITReachabilityType3G;
}else if([technology isEqualToString:CTRadioAccessTechnologyLTE]){
radioType = BITReachabilityTypeLTE;
}
return radioType;
}
- (NSString *)descriptionForReachabilityType:(BITReachabilityType)reachabilityType{
switch(reachabilityType){
case BITReachabilityTypeWIFI:
return @"WIFI";
case BITReachabilityTypeWWAN:
return @"WWAN";
case BITReachabilityTypeGPRS:
return @"GPRS";
case BITReachabilityTypeEDGE:
return @"EDGE";
case BITReachabilityType3G:
return @"3G";
case BITReachabilityTypeLTE:
return @"LTE";
default:
return @"None";
}
}
@end

View File

@ -105,6 +105,10 @@
1B87EFCA1B8D30AC0007C96B /* BITOrderedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B87EFC71B8D30AC0007C96B /* BITOrderedDictionary.h */; }; 1B87EFCA1B8D30AC0007C96B /* BITOrderedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B87EFC71B8D30AC0007C96B /* BITOrderedDictionary.h */; };
1B87EFCB1B8D30AC0007C96B /* BITOrderedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B87EFC81B8D30AC0007C96B /* BITOrderedDictionary.m */; }; 1B87EFCB1B8D30AC0007C96B /* BITOrderedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B87EFC81B8D30AC0007C96B /* BITOrderedDictionary.m */; };
1B87EFCC1B8D30AC0007C96B /* BITOrderedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B87EFC81B8D30AC0007C96B /* BITOrderedDictionary.m */; }; 1B87EFCC1B8D30AC0007C96B /* BITOrderedDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B87EFC81B8D30AC0007C96B /* BITOrderedDictionary.m */; };
1B98D45A1B98F6CA00B8000B /* BITReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B98D4571B98F6CA00B8000B /* BITReachability.h */; };
1B98D45B1B98F6CA00B8000B /* BITReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 1B98D4571B98F6CA00B8000B /* BITReachability.h */; };
1B98D45C1B98F6CA00B8000B /* BITReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B98D4581B98F6CA00B8000B /* BITReachability.m */; };
1B98D45D1B98F6CA00B8000B /* BITReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B98D4581B98F6CA00B8000B /* BITReachability.m */; };
1BD33EAA1B950BC200C3368B /* BITSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BD33EA91B950BC200C3368B /* BITSessionTests.m */; }; 1BD33EAA1B950BC200C3368B /* BITSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BD33EA91B950BC200C3368B /* BITSessionTests.m */; };
1BD33EAB1B950BC200C3368B /* BITSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BD33EA91B950BC200C3368B /* BITSessionTests.m */; }; 1BD33EAB1B950BC200C3368B /* BITSessionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1BD33EA91B950BC200C3368B /* BITSessionTests.m */; };
1BD33EAF1B950DC700C3368B /* BITChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 1BD33EAD1B950DC700C3368B /* BITChannel.h */; }; 1BD33EAF1B950DC700C3368B /* BITChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 1BD33EAD1B950DC700C3368B /* BITChannel.h */; };
@ -500,6 +504,8 @@
1B87EFC21B8D2FBA0007C96B /* BITTelemetryObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITTelemetryObject.m; sourceTree = "<group>"; }; 1B87EFC21B8D2FBA0007C96B /* BITTelemetryObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITTelemetryObject.m; sourceTree = "<group>"; };
1B87EFC71B8D30AC0007C96B /* BITOrderedDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITOrderedDictionary.h; sourceTree = "<group>"; }; 1B87EFC71B8D30AC0007C96B /* BITOrderedDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITOrderedDictionary.h; sourceTree = "<group>"; };
1B87EFC81B8D30AC0007C96B /* BITOrderedDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITOrderedDictionary.m; sourceTree = "<group>"; }; 1B87EFC81B8D30AC0007C96B /* BITOrderedDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITOrderedDictionary.m; sourceTree = "<group>"; };
1B98D4571B98F6CA00B8000B /* BITReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITReachability.h; sourceTree = "<group>"; };
1B98D4581B98F6CA00B8000B /* BITReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITReachability.m; sourceTree = "<group>"; };
1BD33EA91B950BC200C3368B /* BITSessionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITSessionTests.m; sourceTree = "<group>"; }; 1BD33EA91B950BC200C3368B /* BITSessionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITSessionTests.m; sourceTree = "<group>"; };
1BD33EAD1B950DC700C3368B /* BITChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITChannel.h; sourceTree = "<group>"; }; 1BD33EAD1B950DC700C3368B /* BITChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITChannel.h; sourceTree = "<group>"; };
1BD33EAE1B950DC700C3368B /* BITChannel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITChannel.m; sourceTree = "<group>"; }; 1BD33EAE1B950DC700C3368B /* BITChannel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITChannel.m; sourceTree = "<group>"; };
@ -1278,6 +1284,7 @@
1E49A4421612223B00463151 /* BITFeedbackListViewCell.h in Headers */, 1E49A4421612223B00463151 /* BITFeedbackListViewCell.h in Headers */,
1B330A5B1B98DFC7007844AB /* BITData.h in Headers */, 1B330A5B1B98DFC7007844AB /* BITData.h in Headers */,
1E49A4541612223B00463151 /* BITFeedbackManagerPrivate.h in Headers */, 1E49A4541612223B00463151 /* BITFeedbackManagerPrivate.h in Headers */,
1B98D45A1B98F6CA00B8000B /* BITReachability.h in Headers */,
1E49A4571612223B00463151 /* BITFeedbackMessage.h in Headers */, 1E49A4571612223B00463151 /* BITFeedbackMessage.h in Headers */,
1E49A45D1612223B00463151 /* BITFeedbackUserDataViewController.h in Headers */, 1E49A45D1612223B00463151 /* BITFeedbackUserDataViewController.h in Headers */,
1B87EFBC1B8D2EF50007C96B /* BITSession.h in Headers */, 1B87EFBC1B8D2EF50007C96B /* BITSession.h in Headers */,
@ -1356,6 +1363,7 @@
1EB6176F1B0A30D20035A986 /* BITHockeyAttachment.h in Headers */, 1EB6176F1B0A30D20035A986 /* BITHockeyAttachment.h in Headers */,
1B330A5C1B98DFC7007844AB /* BITData.h in Headers */, 1B330A5C1B98DFC7007844AB /* BITData.h in Headers */,
1EB617A61B0A319F0035A986 /* BITUpdateManagerPrivate.h in Headers */, 1EB617A61B0A319F0035A986 /* BITUpdateManagerPrivate.h in Headers */,
1B98D45B1B98F6CA00B8000B /* BITReachability.h in Headers */,
1EB617A41B0A31940035A986 /* BITUpdateManager.h in Headers */, 1EB617A41B0A31940035A986 /* BITUpdateManager.h in Headers */,
1EB617AC1B0A31BA0035A986 /* BITHockeyManager.h in Headers */, 1EB617AC1B0A31BA0035A986 /* BITHockeyManager.h in Headers */,
1B87EFBD1B8D2EF50007C96B /* BITSession.h in Headers */, 1B87EFBD1B8D2EF50007C96B /* BITSession.h in Headers */,
@ -1707,6 +1715,7 @@
1B87EFBE1B8D2EF50007C96B /* BITSession.m in Sources */, 1B87EFBE1B8D2EF50007C96B /* BITSession.m in Sources */,
1E49A4B2161222B900463151 /* BITHockeyBaseManager.m in Sources */, 1E49A4B2161222B900463151 /* BITHockeyBaseManager.m in Sources */,
1B330A931B98EDE5007844AB /* BITLocation.m in Sources */, 1B330A931B98EDE5007844AB /* BITLocation.m in Sources */,
1B98D45C1B98F6CA00B8000B /* BITReachability.m in Sources */,
B27FBEFF1B9622700082406A /* BITPersistence.m in Sources */, B27FBEFF1B9622700082406A /* BITPersistence.m in Sources */,
973EC8C018BE2B5B00DBFFBB /* BITBlurImageAnnotation.m in Sources */, 973EC8C018BE2B5B00DBFFBB /* BITBlurImageAnnotation.m in Sources */,
9760F6D018BB685600959B93 /* BITImageAnnotation.m in Sources */, 9760F6D018BB685600959B93 /* BITImageAnnotation.m in Sources */,
@ -1798,6 +1807,7 @@
1B87EFBF1B8D2EF50007C96B /* BITSession.m in Sources */, 1B87EFBF1B8D2EF50007C96B /* BITSession.m in Sources */,
1EB617851B0A313A0035A986 /* BITRectangleImageAnnotation.m in Sources */, 1EB617851B0A313A0035A986 /* BITRectangleImageAnnotation.m in Sources */,
1B330A941B98EDE5007844AB /* BITLocation.m in Sources */, 1B330A941B98EDE5007844AB /* BITLocation.m in Sources */,
1B98D45D1B98F6CA00B8000B /* BITReachability.m in Sources */,
B27FBF001B9622700082406A /* BITPersistence.m in Sources */, B27FBF001B9622700082406A /* BITPersistence.m in Sources */,
1EB6177E1B0A31200035A986 /* BITCrashAttachment.m in Sources */, 1EB6177E1B0A31200035A986 /* BITCrashAttachment.m in Sources */,
1EB6176E1B0A30CF0035A986 /* BITWebTableViewCell.m in Sources */, 1EB6176E1B0A30CF0035A986 /* BITWebTableViewCell.m in Sources */,