feat(ios): users can get cell type from hippynetinfo module

This commit is contained in:
mengyanluo
2021-06-11 18:14:37 +08:00
committed by luomy
parent 001f3ce2ac
commit bd271bbf70
5 changed files with 304 additions and 118 deletions
@@ -171,6 +171,7 @@
85BCD46F2578C58000638DB4 /* js_native_api_jsc.cc in Sources */ = {isa = PBXBuildFile; fileRef = 85BCD4342578C58000638DB4 /* js_native_api_jsc.cc */; };
85BCD47C257A0AFE00638DB4 /* ios_loader.cc in Sources */ = {isa = PBXBuildFile; fileRef = 85BCD477257A0AFD00638DB4 /* ios_loader.cc */; };
AC63515623F92C99007FABA5 /* TTTGB-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = AC63515523F92C99007FABA5 /* TTTGB-Medium.otf */; };
F43BE80F26733F620080999C /* HippyNetInfoIntenal.m in Sources */ = {isa = PBXBuildFile; fileRef = F43BE80E26733F620080999C /* HippyNetInfoIntenal.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -475,7 +476,6 @@
06FF8EED2511C20900C03900 /* NSData+DataType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSData+DataType.h"; sourceTree = "<group>"; };
06FF8EEE2511C20900C03900 /* NSData+DataType.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSData+DataType.m"; sourceTree = "<group>"; };
851AD1F32656388E007AF2B0 /* string_view_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_view_utils.h; sourceTree = "<group>"; };
851AD1F42656455D007AF2B0 /* unicode_string_view.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unicode_string_view.h; sourceTree = "<group>"; };
851AD1F526564568007AF2B0 /* unicode_string_view.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = unicode_string_view.cc; sourceTree = "<group>"; };
854FC5C8262F0D88002EAD41 /* logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logging.h; sourceTree = "<group>"; };
854FC5C9262F0D88002EAD41 /* log_level.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log_level.h; sourceTree = "<group>"; };
@@ -539,6 +539,8 @@
85BCD475257A0AFD00638DB4 /* ios_loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ios_loader.h; sourceTree = "<group>"; };
85BCD477257A0AFD00638DB4 /* ios_loader.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ios_loader.cc; sourceTree = "<group>"; };
AC63515523F92C99007FABA5 /* TTTGB-Medium.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "TTTGB-Medium.otf"; sourceTree = "<group>"; };
F43BE80D26733F620080999C /* HippyNetInfoIntenal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HippyNetInfoIntenal.h; sourceTree = "<group>"; };
F43BE80E26733F620080999C /* HippyNetInfoIntenal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HippyNetInfoIntenal.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -719,6 +721,8 @@
children = (
064C58EC23AB1A51001E80DD /* HippyNetInfo.h */,
064C58ED23AB1A51001E80DD /* HippyNetInfo.m */,
F43BE80D26733F620080999C /* HippyNetInfoIntenal.h */,
F43BE80E26733F620080999C /* HippyNetInfoIntenal.m */,
);
path = netinfo;
sourceTree = "<group>";
@@ -1279,7 +1283,6 @@
children = (
85BCD3EC2578C57F00638DB4 /* engine.h */,
85BCD3ED2578C57F00638DB4 /* core.h */,
85BCD3EE2578C57F00638DB4 /* platform */,
85BCD3F02578C57F00638DB4 /* task */,
85BCD3F52578C57F00638DB4 /* modules */,
85BCD3FB2578C57F00638DB4 /* scope.h */,
@@ -1289,14 +1292,6 @@
path = core;
sourceTree = "<group>";
};
85BCD3EE2578C57F00638DB4 /* platform */ = {
isa = PBXGroup;
children = (
85BCD3EF2578C57F00638DB4 /* logging_impl.h */,
);
path = platform;
sourceTree = "<group>";
};
85BCD3F02578C57F00638DB4 /* task */ = {
isa = PBXGroup;
children = (
@@ -1365,7 +1360,6 @@
children = (
85BCD4152578C58000638DB4 /* scope.cc */,
85BCD4162578C58000638DB4 /* engine.cc */,
85BCD4172578C58000638DB4 /* platform */,
85BCD4192578C58000638DB4 /* task */,
85BCD41E2578C58000638DB4 /* modules */,
85BCD4232578C58000638DB4 /* base */,
@@ -1374,13 +1368,6 @@
path = src;
sourceTree = "<group>";
};
85BCD4172578C58000638DB4 /* platform */ = {
isa = PBXGroup;
children = (
);
path = platform;
sourceTree = "<group>";
};
85BCD4192578C58000638DB4 /* task */ = {
isa = PBXGroup;
children = (
@@ -1642,6 +1629,7 @@
064C5A0B23AB1A51001E80DD /* HippyRefreshWrapperItemViewManager.m in Sources */,
064C5A1323AB1A51001E80DD /* HippyTextViewManager.mm in Sources */,
854FC5E5262F0D88002EAD41 /* log_settings.cc in Sources */,
F43BE80F26733F620080999C /* HippyNetInfoIntenal.m in Sources */,
0612F03423A8BE330079E622 /* main.m in Sources */,
064C5A5623AB1A51001E80DD /* HippyModuleData.mm in Sources */,
064C5A4723AB1A51001E80DD /* HippyTouchHandler.m in Sources */,
-2
View File
@@ -27,6 +27,4 @@
@interface HippyNetInfo : HippyEventObserverModule <HippyInvalidating>
- (instancetype)initWithHost:(NSString *)host;
@end
+25 -98
View File
@@ -25,108 +25,49 @@
#import "HippyAssert.h"
#import "HippyBridge.h"
#import "HippyEventDispatcher.h"
#import "netinet/in.h"
#import "HippyNetInfoIntenal.h"
static NSString *const HippyReachabilityStateUnknown = @"UNKNOWN";
static NSString *const HippyReachabilityStateNone = @"NONE";
static NSString *const HippyReachabilityStateWifi = @"WIFI";
static NSString *const HippyReachabilityStateCell = @"CELL";
@interface HippyNetInfo ()<HippyNetworkTypeChangedDelegate> {
}
@implementation HippyNetInfo {
SCNetworkReachabilityRef _reachability;
NSString *_networkType;
NSString *_host;
@end
@implementation HippyNetInfo
static NSDictionary *callbackParamFromCellType(HippyNetworkTypeObject *object) {
if (!object) {
return @{};
}
NSString *networkType = object.networkType?:HippyNetworkTypeUnknown;
NSString *cellType = object.cellType?:HippNetworkCellTypeUnknown;
return @{@"network_info": networkType, @"network_type":cellType};
}
HIPPY_EXPORT_MODULE()
static NSString *hippyReachabilityTypeFromFlags(SCNetworkReachabilityFlags flags) {
NSString *networkType = HippyReachabilityStateUnknown;
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0 || (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0) {
networkType = HippyReachabilityStateNone;
} else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
networkType = HippyReachabilityStateCell;
} else {
networkType = HippyReachabilityStateWifi;
}
return networkType;
}
static NSString *currentReachabilityType(SCNetworkReachabilityRef reachabilityRef) {
SCNetworkReachabilityFlags flags;
BOOL success = SCNetworkReachabilityGetFlags(reachabilityRef, &flags);
if (success) {
NSString *type = hippyReachabilityTypeFromFlags(flags);
return type ?: HippyReachabilityStateUnknown;
} else {
return HippyReachabilityStateUnknown;
}
}
static SCNetworkReachabilityRef createReachabilityRefWithZeroAddress() {
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr *)&zeroAddress);
return reachability;
}
static void HippyReachabilityCallback(__unused SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) {
HippyNetInfo *self = (__bridge id)info;
NSString *networkType = hippyReachabilityTypeFromFlags(flags);
if (![networkType isEqualToString:self->_networkType]) {
self->_networkType = networkType;
[self sendEvent:@"networkStatusDidChange" params:@ { @"network_info": networkType }];
}
}
#pragma mark - Lifecycle
- (instancetype)initWithHost:(NSString *)host {
HippyAssertParam(host);
HippyAssert(![host hasPrefix:@"http"], @"Host value should just contain the domain, not the URL scheme.");
if ((self = [self init])) {
_host = [host copy];
}
return self;
}
- (void)addEventObserverForName:(NSString *)eventName {
if ([eventName isEqualToString:@"networkStatusDidChange"]) {
if (!_reachability) {
_reachability = createReachabilityRefWithZeroAddress();
SCNetworkReachabilityContext context = { 0, (__bridge void *)self, NULL, NULL, NULL };
SCNetworkReachabilitySetCallback(_reachability, HippyReachabilityCallback, &context);
SCNetworkReachabilityScheduleWithRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}
_networkType = currentReachabilityType(_reachability);
[self sendEvent:@"networkStatusDidChange" params:@{ @"network_info": _networkType }];
HippyNetworkTypeObject *networkType = [[HippyNetInfoIntenal sharedInstance] addNetworkTypeChangeObserver:self];
NSDictionary *params = callbackParamFromCellType(networkType);
[self sendEvent:@"networkStatusDidChange" params:params];
}
}
- (void)removeEventObserverForName:(NSString *)eventName {
if ([eventName isEqualToString:@"networkStatusDidChange"]) {
[self releaseReachability];
[[HippyNetInfoIntenal sharedInstance] removeNetworkTypeChangeObserver:self];
}
}
- (void)invalidate {
[self releaseReachability];
}
- (void)releaseReachability {
if (_reachability) {
SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFRelease(_reachability);
_reachability = NULL;
}
- (void)hippyNetworkTypeChanged:(HippyNetworkTypeObject *)networkType {
NSDictionary *params = callbackParamFromCellType(networkType);
[self sendEvent:@"networkStatusDidChange" params:params];
}
- (void)dealloc {
[self releaseReachability];
}
#pragma mark - Public API
// clang-format off
@@ -135,23 +76,9 @@ HIPPY_EXPORT_METHOD(getCurrentConnectivity:(HippyPromiseResolveBlock)resolve
if (!resolve) {
return;
}
//return network type if it was set and not unknown type
if (_networkType) {
resolve(@{@"network_info": _networkType});
}
//else try to get network type
else {
SCNetworkReachabilityRef reachability = NULL;
if (_reachability) {
reachability = CFRetain(_reachability);
}
else {
reachability = createReachabilityRefWithZeroAddress();
}
NSString *type = currentReachabilityType(reachability);
resolve(@{@"network_info": type});
CFRelease(reachability);
}
HippyNetworkTypeObject *obj = [[HippyNetInfoIntenal sharedInstance] currentNetworkType];
NSDictionary *dic = callbackParamFromCellType(obj);
resolve(dic);
}
// clang-format on
@@ -0,0 +1,68 @@
//
// HippyNetInfoIntenal.h
// HippyDemo
//
// Created by mengyanluo on 2021/6/11.
// Copyright © 2021 tencent. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
extern NSString *const HippyNetworkTypeUnknown;
extern NSString *const HippyNetworkTypeNone;
extern NSString *const HippyNetworkTypeWifi;
extern NSString *const HippyNetworkTypeCell;
extern NSString *const HippNetworkCellTypeUnknown;
extern NSString *const HippNetworkCellTypeNone;
extern NSString *const HippyNetworkCellType2G;
extern NSString *const HippyNetworkCellType3G;
extern NSString *const HippyNetworkCellType4G;
extern NSString *const HippyNetworkCellType5G;
@interface HippyNetworkTypeObject : NSObject
/**
* indicate network type
* value:HippyNetworkTypeUnknown,HippyNetworkTypeNone,HippyNetworkTypeWifi,HippyNetworkTypeCell
*/
@property(nonatomic, readonly) NSString *networkType;
/**
* indicate cell type
*/
@property(nonatomic, readonly) NSString *cellType;
- (instancetype)initWithNetworkType:(NSString *)networkType cellType:(NSString *)cellType;
- (BOOL)isEqual:(id)object;
- (BOOL)isEqualToNetowrkTypeObject:(HippyNetworkTypeObject *)object;
@end
@protocol HippyNetworkTypeChangedDelegate <NSObject>
- (void)hippyNetworkTypeChanged:(HippyNetworkTypeObject *)networkType;
@end
@interface HippyNetInfoIntenal : NSObject
+ (instancetype)sharedInstance;
- (HippyNetworkTypeObject *)currentNetworkType;
/**
* set an observer for network changed event.
* return current network info immediately
*/
- (HippyNetworkTypeObject *)addNetworkTypeChangeObserver:(id<HippyNetworkTypeChangedDelegate>)observer;
- (void)removeNetworkTypeChangeObserver:(id<HippyNetworkTypeChangedDelegate>)observer;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,205 @@
//
// HippyNetInfoIntenal.m
// HippyDemo
//
// Created by mengyanluo on 2021/6/11.
// Copyright © 2021 tencent. All rights reserved.
//
#import "HippyNetInfoIntenal.h"
#import "HippyAssert.h"
#import "HippyBridge.h"
#import "HippyEventDispatcher.h"
#import "netinet/in.h"
#import <SystemConfiguration/SystemConfiguration.h>
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
NSString *const HippyNetworkTypeUnknown = @"UNKNOWN";
NSString *const HippyNetworkTypeNone = @"NONE";
NSString *const HippyNetworkTypeWifi = @"WIFI";
NSString *const HippyNetworkTypeCell = @"CELL";
NSString *const HippNetworkCellTypeUnknown = @"UNKNOWN";
NSString *const HippNetworkCellTypeNone = @"NONE";
NSString *const HippyNetworkCellType2G = @"2G";
NSString *const HippyNetworkCellType3G = @"3G";
NSString *const HippyNetworkCellType4G = @"4G";
NSString *const HippyNetworkCellType5G = @"5G";
static HippyNetInfoIntenal *instance = nil;
@implementation HippyNetworkTypeObject
- (instancetype)initWithNetworkType:(NSString *)networkType cellType:(NSString *)cellType {
self = [super init];
if (self) {
_networkType = networkType;
_cellType = cellType;
}
return self;
}
- (BOOL)isEqual:(id)object {
return [self isEqualToNetowrkTypeObject:object];
}
- (BOOL)isEqualToNetowrkTypeObject:(HippyNetworkTypeObject *)object {
if ([object isKindOfClass:[HippyNetworkTypeObject class]]) {
if ([self.networkType isEqualToString:object.networkType] &&
[self.cellType isEqualToString:object.cellType]) {
return YES;
}
}
return NO;
}
@end
@interface HippyNetInfoIntenal () {
SCNetworkReachabilityRef _reachability;
NSString *_networkType;
NSString *_host;
CTTelephonyNetworkInfo *_cellNetType;
NSHashTable *_observers;
}
@end
@implementation HippyNetInfoIntenal
static NSString *hippyReachabilityGetCellType(NSString *cellType) {
if ([cellType isEqualToString:CTRadioAccessTechnologyEdge] ||
[cellType isEqualToString:CTRadioAccessTechnologyGPRS] ||
[cellType isEqualToString:CTRadioAccessTechnologyCDMA1x]) {
return HippyNetworkCellType2G;
}
else if ([cellType isEqualToString:CTRadioAccessTechnologyHSDPA] ||
[cellType isEqualToString:CTRadioAccessTechnologyWCDMA] ||
[cellType isEqualToString:CTRadioAccessTechnologyHSUPA] ||
[cellType isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0] ||
[cellType isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA] ||
[cellType isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB] ||
[cellType isEqualToString:CTRadioAccessTechnologyeHRPD]) {
return HippyNetworkCellType3G;
}
else if ([cellType isEqualToString:CTRadioAccessTechnologyLTE]) {
return HippyNetworkCellType4G;
}
else if (@available(iOS 14.1, *)) {
if ([cellType isEqualToString:CTRadioAccessTechnologyNRNSA] ||
[cellType isEqualToString:CTRadioAccessTechnologyNR]) {
return HippyNetworkCellType5G;
}
}
return HippNetworkCellTypeUnknown;
}
static SCNetworkReachabilityRef createReachabilityRefWithZeroAddress() {
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr *)&zeroAddress);
return reachability;
}
static NSString *hippyReachabilityTypeFromFlags(SCNetworkReachabilityFlags flags) {
NSString *networkType = HippyNetworkTypeUnknown;
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0 || (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0) {
networkType = HippNetworkCellTypeNone;
} else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
networkType = HippyNetworkTypeCell;
} else {
networkType = HippyNetworkTypeWifi;
}
return networkType;
}
static NSString *currentReachabilityType(SCNetworkReachabilityRef reachabilityRef) {
SCNetworkReachabilityFlags flags;
BOOL success = SCNetworkReachabilityGetFlags(reachabilityRef, &flags);
if (success) {
NSString *type = hippyReachabilityTypeFromFlags(flags);
return type ?: HippyNetworkTypeUnknown;
} else {
return HippyNetworkTypeUnknown;
}
}
static void reachabilityCallback(__unused SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info) {
HippyNetInfoIntenal *netinfo = (__bridge HippyNetInfoIntenal *)info;
NSString *networkType = hippyReachabilityTypeFromFlags(flags);
NSString *cellType = hippyReachabilityGetCellType(netinfo->_cellNetType.currentRadioAccessTechnology);
HippyNetworkTypeObject *obj = [[HippyNetworkTypeObject alloc] initWithNetworkType:networkType cellType:cellType];
[netinfo notifyObserversNetworkTypeChanged:obj];
}
+ (instancetype)sharedInstance {
return [[self alloc] init];
}
- (instancetype)init {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [super init];
[instance setup];
});
return instance;
}
- (void)setup {
_observers = [NSHashTable weakObjectsHashTable];
_reachability = createReachabilityRefWithZeroAddress();
_cellNetType = [[CTTelephonyNetworkInfo alloc] init];
[self registerNetworkChangedListener];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(radioAccessTechnologyDidChange:) name:CTRadioAccessTechnologyDidChangeNotification object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)radioAccessTechnologyDidChange:(NSNotification *)notification {
HippyNetworkTypeObject *object = [self currentNetworkType];
[self notifyObserversNetworkTypeChanged:object];
}
- (void)registerNetworkChangedListener {
SCNetworkReachabilityContext context = { 0, (__bridge void *)self, NULL, NULL, NULL };
SCNetworkReachabilitySetCallback(_reachability, reachabilityCallback, &context);
SCNetworkReachabilityScheduleWithRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
}
- (HippyNetworkTypeObject *)addNetworkTypeChangeObserver:(id<HippyNetworkTypeChangedDelegate>)observer {
HippyAssert([observer respondsToSelector:@selector(hippyNetworkTypeChanged:)], @"observer shoud conform HippyNetworkTypeChangedDelegate");
if (observer) {
[_observers addObject:observer];
}
return [self currentNetworkType];
}
- (void)removeNetworkTypeChangeObserver:(id<HippyNetworkTypeChangedDelegate>)observer {
[_observers removeObject:observer];
}
- (HippyNetworkTypeObject *)currentNetworkType {
NSString *networkType = currentReachabilityType(_reachability);
NSString *cellType = hippyReachabilityGetCellType(_cellNetType.currentRadioAccessTechnology);
HippyNetworkTypeObject *obj = [[HippyNetworkTypeObject alloc] initWithNetworkType:networkType cellType:cellType];
return obj;
}
- (void)notifyObserversNetworkTypeChanged:(HippyNetworkTypeObject *)object {
NSArray<id<HippyNetworkTypeChangedDelegate>> *observers = [_observers allObjects];
for (id<HippyNetworkTypeChangedDelegate> observer in observers) {
HippyAssert([observer respondsToSelector:@selector(hippyNetworkTypeChanged:)], @"observer shoud conform HippyNetworkTypeChangedDelegate");
if ([observer respondsToSelector:@selector(hippyNetworkTypeChanged:)]) {
[observer hippyNetworkTypeChanged:object];
}
}
}
@end