react-native/Libraries/Network/RCTNetInfo.m

184 lines
7.0 KiB
Mathematica
Raw Normal View History

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
2015-08-14 12:08:25 +00:00
#import "RCTNetInfo.h"
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
#if !TARGET_OS_TV
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#endif
#import <React/RCTAssert.h>
#import <React/RCTBridge.h>
#import <React/RCTEventDispatcher.h>
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
// Based on the ConnectionType enum described in the W3C Network Information API spec
// (https://wicg.github.io/netinfo/).
static NSString *const RCTConnectionTypeUnknown = @"unknown";
static NSString *const RCTConnectionTypeNone = @"none";
static NSString *const RCTConnectionTypeWifi = @"wifi";
static NSString *const RCTConnectionTypeCellular = @"cellular";
// Based on the EffectiveConnectionType enum described in the W3C Network Information API spec
// (https://wicg.github.io/netinfo/).
static NSString *const RCTEffectiveConnectionTypeUnknown = @"unknown";
static NSString *const RCTEffectiveConnectionType2g = @"2g";
static NSString *const RCTEffectiveConnectionType3g = @"3g";
static NSString *const RCTEffectiveConnectionType4g = @"4g";
// The RCTReachabilityState* values are deprecated.
static NSString *const RCTReachabilityStateUnknown = @"unknown";
static NSString *const RCTReachabilityStateNone = @"none";
static NSString *const RCTReachabilityStateWifi = @"wifi";
static NSString *const RCTReachabilityStateCell = @"cell";
2015-08-14 12:08:25 +00:00
@implementation RCTNetInfo
{
SCNetworkReachabilityRef _firstTimeReachability;
SCNetworkReachabilityRef _reachability;
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
NSString *_connectionType;
NSString *_effectiveConnectionType;
NSString *_statusDeprecated;
NSString *_host;
Fix #8615: NetInfo.isConnected for iOS Summary: This is fixing #8615. The problem was that, on initialization, the `_connectionType` variable was still set to its default value of `RCTConnectionTypeUnknown`. The exposed API method did nothing to determine this unless a subscription had be established and then the method would simply return the last reported value. Instead, the exposed oneshot API call now actually checks the connection status through the same methods as the subscription and updates RCTNetInfo’s values before returning. In order to avoid reporting events without a subscription, a flag is set and unset on calls to start/stopObserving. - start app - observe the (in)correct reporting of the manual status - change network status to offline - press refresh - observe the manual fetch - start subscription - change network status to online - press refresh to show that the manual refresh works (only now working for current RN version) - change network status to offline - stop subscription - change network status to online - press refresh to show manual refresh does(n't) work without subscription - start subscription to show it updates to current Current Behavior: https://drive.google.com/file/d/1Ods6HORgp_vfm1mQVjGwhtH1D7issxjo/view?usp=sharing Fixed Behavior: https://drive.google.com/file/d/11H1UOF33LeMGvXEOoapU62ARDSb7qoYv/view?usp=sharing [IOS] [BUGFIX] [Libraries\Network\RCTNetInfo.m] - Fixed #8615, `iOS: NetInfo.isConnected returns always false`, by decoupling the fetch from the status of the subscription. Closes https://github.com/facebook/react-native/pull/17397 Differential Revision: D7102771 Pulled By: hramos fbshipit-source-id: ea11eb0b1a7ca641fc43da2fe172cf7b2597de4a
2018-02-27 22:11:51 +00:00
BOOL _isObserving;
RCTPromiseResolveBlock _resolve;
}
2015-04-20 15:31:15 +00:00
RCT_EXPORT_MODULE()
static void RCTReachabilityCallback(__unused SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void *info)
{
2015-08-14 12:08:25 +00:00
RCTNetInfo *self = (__bridge id)info;
BOOL didSetReachabilityFlags = [self setReachabilityStatus:flags];
if (self->_firstTimeReachability && self->_resolve) {
SCNetworkReachabilityUnscheduleFromRunLoop(self->_firstTimeReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFRelease(self->_firstTimeReachability);
self->_resolve(@{@"connectionType": self->_connectionType ?: RCTConnectionTypeUnknown,
@"effectiveConnectionType": self->_effectiveConnectionType ?: RCTEffectiveConnectionTypeUnknown,
@"network_info": self->_statusDeprecated ?: RCTReachabilityStateUnknown});
self->_firstTimeReachability = nil;
self->_resolve = nil;
}
if (didSetReachabilityFlags && self->_isObserving) {
Fix #8615: NetInfo.isConnected for iOS Summary: This is fixing #8615. The problem was that, on initialization, the `_connectionType` variable was still set to its default value of `RCTConnectionTypeUnknown`. The exposed API method did nothing to determine this unless a subscription had be established and then the method would simply return the last reported value. Instead, the exposed oneshot API call now actually checks the connection status through the same methods as the subscription and updates RCTNetInfo’s values before returning. In order to avoid reporting events without a subscription, a flag is set and unset on calls to start/stopObserving. - start app - observe the (in)correct reporting of the manual status - change network status to offline - press refresh - observe the manual fetch - start subscription - change network status to online - press refresh to show that the manual refresh works (only now working for current RN version) - change network status to offline - stop subscription - change network status to online - press refresh to show manual refresh does(n't) work without subscription - start subscription to show it updates to current Current Behavior: https://drive.google.com/file/d/1Ods6HORgp_vfm1mQVjGwhtH1D7issxjo/view?usp=sharing Fixed Behavior: https://drive.google.com/file/d/11H1UOF33LeMGvXEOoapU62ARDSb7qoYv/view?usp=sharing [IOS] [BUGFIX] [Libraries\Network\RCTNetInfo.m] - Fixed #8615, `iOS: NetInfo.isConnected returns always false`, by decoupling the fetch from the status of the subscription. Closes https://github.com/facebook/react-native/pull/17397 Differential Revision: D7102771 Pulled By: hramos fbshipit-source-id: ea11eb0b1a7ca641fc43da2fe172cf7b2597de4a
2018-02-27 22:11:51 +00:00
[self sendEventWithName:@"networkStatusDidChange" body:@{@"connectionType": self->_connectionType,
@"effectiveConnectionType": self->_effectiveConnectionType,
@"network_info": self->_statusDeprecated}];
}
}
#pragma mark - Lifecycle
- (instancetype)initWithHost:(NSString *)host
{
RCTAssertParam(host);
RCTAssert(![host hasPrefix:@"http"], @"Host value should just contain the domain, not the URL scheme.");
if ((self = [self init])) {
_host = [host copy];
}
return self;
}
- (NSArray<NSString *> *)supportedEvents
{
return @[@"networkStatusDidChange"];
}
- (void)startObserving
{
_isObserving = YES;
_connectionType = RCTConnectionTypeUnknown;
_effectiveConnectionType = RCTEffectiveConnectionTypeUnknown;
_statusDeprecated = RCTReachabilityStateUnknown;
_reachability = [self getReachabilityRef];
}
- (void)stopObserving
{
_isObserving = NO;
if (_reachability) {
SCNetworkReachabilityUnscheduleFromRunLoop(_reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
CFRelease(_reachability);
}
}
- (SCNetworkReachabilityRef)getReachabilityRef
{
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, _host.UTF8String ?: "apple.com");
SCNetworkReachabilityContext context = { 0, ( __bridge void *)self, NULL, NULL, NULL };
SCNetworkReachabilitySetCallback(reachability, RCTReachabilityCallback, &context);
SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);
return reachability;
}
- (BOOL)setReachabilityStatus:(SCNetworkReachabilityFlags)flags
{
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
NSString *connectionType = RCTConnectionTypeUnknown;
NSString *effectiveConnectionType = RCTEffectiveConnectionTypeUnknown;
NSString *status = RCTReachabilityStateUnknown;
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0 ||
(flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0) {
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
connectionType = RCTConnectionTypeNone;
status = RCTReachabilityStateNone;
}
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
#if !TARGET_OS_TV
else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
connectionType = RCTConnectionTypeCellular;
status = RCTReachabilityStateCell;
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init];
if (netinfo) {
if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS] ||
[netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge] ||
[netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x]) {
effectiveConnectionType = RCTEffectiveConnectionType2g;
} else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyWCDMA] ||
[netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSDPA] ||
[netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSUPA] ||
[netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0] ||
[netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA] ||
[netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB] ||
[netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyeHRPD]) {
effectiveConnectionType = RCTEffectiveConnectionType3g;
} else if ([netinfo.currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE]) {
effectiveConnectionType = RCTEffectiveConnectionType4g;
}
}
}
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
#endif
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
else {
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
connectionType = RCTConnectionTypeWifi;
status = RCTReachabilityStateWifi;
}
DEPRECATION: Make NetInfo API cross platform and expose whether connection is 2g/3g/4g Summary: This change intends to fix 2 issues with the NetInfo API: - The NetInfo API is currently platform-specific. It returns completely different values on iOS and Android. - The NetInfo API currently doesn't expose a way to determine whether the connection is 2g, 3g, or 4g. The NetInfo API currently just exposes a string-based enum representing the connectivity type. The string values are different between iOS and Andorid. Because of this design, it's not obvious how to achieve the goals of this change without making a breaking change. Consequently, this change deprecates the old NetInfo APIs and introduces new ones. Specifically, these are the API changes: - The `fetch` method is deprecated in favor of `getConnection` - The `change` event is deprecated in favor of the `connectionchange` event. - `getConnection`/`connectionchange` use a new set of enum values compared to `fetch`/`change`. See the documentation for the new values. - On iOS, `cell` is now known as `cellular`. It's worth pointing out this one in particular because the old and new names are so similar. The rest of the iOS values have remained the same. - Some of the Android enum values have been removed without a replacement (e.g. `DUMMY`, `MOBILE_DUN`, `MOBILE_HIPRI`, `MOBILE_MMS`, `MOBILE_SUPL`, `VPN`). If desirable, we could find a way to expose these in the new API. For example, we could have a `platformValue` key that exposes the platform's enum values directly (like the old `fetch` API did). `getConnection` and `connectionchange` each expose an object which has 2 keys conveying a `ConnectionType` (e.g. wifi, cellular) and an `EffectiveConnectionType` (e.g. 2g, 3g). These enums and their values are taken directly from the W3C's Network Information API spec (https://wicg.github.io/netinfo/). Copying the W3C's API will make it easy to expose a `navigation.connection` polyfill, if we want, in the future. Additionally, because the new APIs expose an object instead of a string, it's easier to extend the APIs in the future by adding keys to the object without causing a breaking change. Note that the W3C's spec doesn't have an "unknown" value for `EffectiveConnectionType`. I chose to introduce this non-standard value because it's possible for the current implementation to not have an `effectiveConnectionType` and I figured it was worth representing this possibility explicitly with "unknown" instead of implicitly with `null`. **Test Plan (required)** Verified that the methods (`fetch` and `getConnection`) and the events (`change` and `connectionchange`) return the correct data on iOS and Android when connected to a wifi network and a 4G cellular network. Verified that switching networks causes the event to fire with the correct information. Verified that the old APIs (`fetch' and 'change') emit a deprecation warning when used. My team is using a similar patch in our app. Adam Comella Microsoft Corp. Closes https://github.com/facebook/react-native/pull/14618 Differential Revision: D5459593 Pulled By: shergin fbshipit-source-id: f1e6c5d572bb3e2669fbd4ba7d0fbb106525280e
2017-07-24 22:42:27 +00:00
if (![connectionType isEqualToString:self->_connectionType] ||
![effectiveConnectionType isEqualToString:self->_effectiveConnectionType] ||
![status isEqualToString:self->_statusDeprecated]) {
self->_connectionType = connectionType;
self->_effectiveConnectionType = effectiveConnectionType;
self->_statusDeprecated = status;
Fix #8615: NetInfo.isConnected for iOS Summary: This is fixing #8615. The problem was that, on initialization, the `_connectionType` variable was still set to its default value of `RCTConnectionTypeUnknown`. The exposed API method did nothing to determine this unless a subscription had be established and then the method would simply return the last reported value. Instead, the exposed oneshot API call now actually checks the connection status through the same methods as the subscription and updates RCTNetInfo’s values before returning. In order to avoid reporting events without a subscription, a flag is set and unset on calls to start/stopObserving. - start app - observe the (in)correct reporting of the manual status - change network status to offline - press refresh - observe the manual fetch - start subscription - change network status to online - press refresh to show that the manual refresh works (only now working for current RN version) - change network status to offline - stop subscription - change network status to online - press refresh to show manual refresh does(n't) work without subscription - start subscription to show it updates to current Current Behavior: https://drive.google.com/file/d/1Ods6HORgp_vfm1mQVjGwhtH1D7issxjo/view?usp=sharing Fixed Behavior: https://drive.google.com/file/d/11H1UOF33LeMGvXEOoapU62ARDSb7qoYv/view?usp=sharing [IOS] [BUGFIX] [Libraries\Network\RCTNetInfo.m] - Fixed #8615, `iOS: NetInfo.isConnected returns always false`, by decoupling the fetch from the status of the subscription. Closes https://github.com/facebook/react-native/pull/17397 Differential Revision: D7102771 Pulled By: hramos fbshipit-source-id: ea11eb0b1a7ca641fc43da2fe172cf7b2597de4a
2018-02-27 22:11:51 +00:00
return YES;
}
Fix #8615: NetInfo.isConnected for iOS Summary: This is fixing #8615. The problem was that, on initialization, the `_connectionType` variable was still set to its default value of `RCTConnectionTypeUnknown`. The exposed API method did nothing to determine this unless a subscription had be established and then the method would simply return the last reported value. Instead, the exposed oneshot API call now actually checks the connection status through the same methods as the subscription and updates RCTNetInfo’s values before returning. In order to avoid reporting events without a subscription, a flag is set and unset on calls to start/stopObserving. - start app - observe the (in)correct reporting of the manual status - change network status to offline - press refresh - observe the manual fetch - start subscription - change network status to online - press refresh to show that the manual refresh works (only now working for current RN version) - change network status to offline - stop subscription - change network status to online - press refresh to show manual refresh does(n't) work without subscription - start subscription to show it updates to current Current Behavior: https://drive.google.com/file/d/1Ods6HORgp_vfm1mQVjGwhtH1D7issxjo/view?usp=sharing Fixed Behavior: https://drive.google.com/file/d/11H1UOF33LeMGvXEOoapU62ARDSb7qoYv/view?usp=sharing [IOS] [BUGFIX] [Libraries\Network\RCTNetInfo.m] - Fixed #8615, `iOS: NetInfo.isConnected returns always false`, by decoupling the fetch from the status of the subscription. Closes https://github.com/facebook/react-native/pull/17397 Differential Revision: D7102771 Pulled By: hramos fbshipit-source-id: ea11eb0b1a7ca641fc43da2fe172cf7b2597de4a
2018-02-27 22:11:51 +00:00
return NO;
}
#pragma mark - Public API
RCT_EXPORT_METHOD(getCurrentConnectivity:(RCTPromiseResolveBlock)resolve
reject:(__unused RCTPromiseRejectBlock)reject)
{
_firstTimeReachability = [self getReachabilityRef];
_resolve = resolve;
}
@end