|
| 1 | +/** |
| 2 | + * Copyright (c) 2015-present, Facebook, Inc. |
| 3 | + * |
| 4 | + * This source code is licensed under the MIT license found in the |
| 5 | + * LICENSE file in the root directory of this source tree. |
| 6 | + * |
| 7 | + * @format |
| 8 | + * @flow |
| 9 | + */ |
| 10 | + |
| 11 | +'use strict'; |
| 12 | + |
| 13 | +const Map = require('Map'); |
| 14 | +const NativeEventEmitter = require('NativeEventEmitter'); |
| 15 | +const NativeModules = require('NativeModules'); |
| 16 | +const Platform = require('Platform'); |
| 17 | +const RCTNetInfo = NativeModules.NetInfo; |
| 18 | + |
| 19 | +const NetInfoEventEmitter = new NativeEventEmitter(RCTNetInfo); |
| 20 | + |
| 21 | +const DEVICE_CONNECTIVITY_EVENT = 'networkStatusDidChange'; |
| 22 | + |
| 23 | +type ChangeEventName = $Enum<{ |
| 24 | + connectionChange: string, |
| 25 | + change: string, |
| 26 | +}>; |
| 27 | + |
| 28 | +type ReachabilityStateIOS = $Enum<{ |
| 29 | + cell: string, |
| 30 | + none: string, |
| 31 | + unknown: string, |
| 32 | + wifi: string, |
| 33 | +}>; |
| 34 | + |
| 35 | +type ConnectivityStateAndroid = $Enum<{ |
| 36 | + NONE: string, |
| 37 | + MOBILE: string, |
| 38 | + WIFI: string, |
| 39 | + MOBILE_MMS: string, |
| 40 | + MOBILE_SUPL: string, |
| 41 | + MOBILE_DUN: string, |
| 42 | + MOBILE_HIPRI: string, |
| 43 | + WIMAX: string, |
| 44 | + BLUETOOTH: string, |
| 45 | + DUMMY: string, |
| 46 | + ETHERNET: string, |
| 47 | + MOBILE_FOTA: string, |
| 48 | + MOBILE_IMS: string, |
| 49 | + MOBILE_CBS: string, |
| 50 | + WIFI_P2P: string, |
| 51 | + MOBILE_IA: string, |
| 52 | + MOBILE_EMERGENCY: string, |
| 53 | + PROXY: string, |
| 54 | + VPN: string, |
| 55 | + UNKNOWN: string, |
| 56 | +}>; |
| 57 | + |
| 58 | +const _subscriptions = new Map(); |
| 59 | + |
| 60 | +let _isConnectedDeprecated; |
| 61 | +if (Platform.OS === 'ios') { |
| 62 | + _isConnectedDeprecated = function( |
| 63 | + reachability: ReachabilityStateIOS, |
| 64 | + ): boolean { |
| 65 | + return reachability !== 'none' && reachability !== 'unknown'; |
| 66 | + }; |
| 67 | +} else if (Platform.OS === 'android') { |
| 68 | + _isConnectedDeprecated = function( |
| 69 | + connectionType: ConnectivityStateAndroid, |
| 70 | + ): boolean { |
| 71 | + return connectionType !== 'NONE' && connectionType !== 'UNKNOWN'; |
| 72 | + }; |
| 73 | +} |
| 74 | + |
| 75 | +function _isConnected(connection) { |
| 76 | + return connection.type !== 'none' && connection.type !== 'unknown'; |
| 77 | +} |
| 78 | + |
| 79 | +const _isConnectedSubscriptions = new Map(); |
| 80 | + |
| 81 | +/** |
| 82 | + * NetInfo exposes info about online/offline status. |
| 83 | + * |
| 84 | + * See https://facebook.github.io/react-native/docs/netinfo.html |
| 85 | + */ |
| 86 | +const NetInfo = { |
| 87 | + /** |
| 88 | + * Adds an event handler. |
| 89 | + * |
| 90 | + * See https://facebook.github.io/react-native/docs/netinfo.html#addeventlistener |
| 91 | + */ |
| 92 | + addEventListener( |
| 93 | + eventName: ChangeEventName, |
| 94 | + handler: Function, |
| 95 | + ): {remove: () => void} { |
| 96 | + let listener; |
| 97 | + if (eventName === 'connectionChange') { |
| 98 | + listener = NetInfoEventEmitter.addListener( |
| 99 | + DEVICE_CONNECTIVITY_EVENT, |
| 100 | + appStateData => { |
| 101 | + handler({ |
| 102 | + type: appStateData.connectionType, |
| 103 | + effectiveType: appStateData.effectiveConnectionType, |
| 104 | + }); |
| 105 | + }, |
| 106 | + ); |
| 107 | + } else if (eventName === 'change') { |
| 108 | + console.warn( |
| 109 | + 'NetInfo\'s "change" event is deprecated. Listen to the "connectionChange" event instead.', |
| 110 | + ); |
| 111 | + |
| 112 | + listener = NetInfoEventEmitter.addListener( |
| 113 | + DEVICE_CONNECTIVITY_EVENT, |
| 114 | + appStateData => { |
| 115 | + handler(appStateData.network_info); |
| 116 | + }, |
| 117 | + ); |
| 118 | + } else { |
| 119 | + console.warn('Trying to subscribe to unknown event: "' + eventName + '"'); |
| 120 | + return { |
| 121 | + remove: () => {}, |
| 122 | + }; |
| 123 | + } |
| 124 | + |
| 125 | + _subscriptions.set(handler, listener); |
| 126 | + return { |
| 127 | + remove: () => NetInfo.removeEventListener(eventName, handler), |
| 128 | + }; |
| 129 | + }, |
| 130 | + |
| 131 | + /** |
| 132 | + * Removes the listener for network status changes. |
| 133 | + * |
| 134 | + * See https://facebook.github.io/react-native/docs/netinfo.html#removeeventlistener |
| 135 | + */ |
| 136 | + removeEventListener(eventName: ChangeEventName, handler: Function): void { |
| 137 | + const listener = _subscriptions.get(handler); |
| 138 | + if (!listener) { |
| 139 | + return; |
| 140 | + } |
| 141 | + listener.remove(); |
| 142 | + _subscriptions.delete(handler); |
| 143 | + }, |
| 144 | + |
| 145 | + /** |
| 146 | + * This function is deprecated. Use `getConnectionInfo` instead. |
| 147 | + * Returns a promise that resolves with one of the deprecated connectivity |
| 148 | + * types: |
| 149 | + * |
| 150 | + * The following connectivity types are deprecated. They're used by the |
| 151 | + * deprecated APIs `fetch` and the `change` event. |
| 152 | + * |
| 153 | + * iOS connectivity types (deprecated): |
| 154 | + * - `none` - device is offline |
| 155 | + * - `wifi` - device is online and connected via wifi, or is the iOS simulator |
| 156 | + * - `cell` - device is connected via Edge, 3G, WiMax, or LTE |
| 157 | + * - `unknown` - error case and the network status is unknown |
| 158 | + * |
| 159 | + * Android connectivity types (deprecated). |
| 160 | + * - `NONE` - device is offline |
| 161 | + * - `BLUETOOTH` - The Bluetooth data connection. |
| 162 | + * - `DUMMY` - Dummy data connection. |
| 163 | + * - `ETHERNET` - The Ethernet data connection. |
| 164 | + * - `MOBILE` - The Mobile data connection. |
| 165 | + * - `MOBILE_DUN` - A DUN-specific Mobile data connection. |
| 166 | + * - `MOBILE_HIPRI` - A High Priority Mobile data connection. |
| 167 | + * - `MOBILE_MMS` - An MMS-specific Mobile data connection. |
| 168 | + * - `MOBILE_SUPL` - A SUPL-specific Mobile data connection. |
| 169 | + * - `VPN` - A virtual network using one or more native bearers. Requires |
| 170 | + * API Level 21 |
| 171 | + * - `WIFI` - The WIFI data connection. |
| 172 | + * - `WIMAX` - The WiMAX data connection. |
| 173 | + * - `UNKNOWN` - Unknown data connection. |
| 174 | + * |
| 175 | + * The rest of the connectivity types are hidden by the Android API, but can |
| 176 | + * be used if necessary. |
| 177 | + */ |
| 178 | + fetch(): Promise<any> { |
| 179 | + console.warn( |
| 180 | + 'NetInfo.fetch() is deprecated. Use NetInfo.getConnectionInfo() instead.', |
| 181 | + ); |
| 182 | + return RCTNetInfo.getCurrentConnectivity().then(resp => resp.network_info); |
| 183 | + }, |
| 184 | + |
| 185 | + /** |
| 186 | + * See https://facebook.github.io/react-native/docs/netinfo.html#getconnectioninfo |
| 187 | + */ |
| 188 | + getConnectionInfo(): Promise<any> { |
| 189 | + return RCTNetInfo.getCurrentConnectivity().then(resp => { |
| 190 | + return { |
| 191 | + type: resp.connectionType, |
| 192 | + effectiveType: resp.effectiveConnectionType, |
| 193 | + }; |
| 194 | + }); |
| 195 | + }, |
| 196 | + |
| 197 | + /** |
| 198 | + * See https://facebook.github.io/react-native/docs/netinfo.html#getconnectioninfo |
| 199 | + */ |
| 200 | + setConnectionCheckUrl(url: string): void { |
| 201 | + RCTNetInfo.setConnectionCheckUrl(url); |
| 202 | + }, |
| 203 | + |
| 204 | + /** |
| 205 | + * An object with the same methods as above but the listener receives a |
| 206 | + * boolean which represents the internet connectivity. |
| 207 | + * |
| 208 | + * See https://facebook.github.io/react-native/docs/netinfo.html#isconnected |
| 209 | + */ |
| 210 | + isConnected: { |
| 211 | + addEventListener( |
| 212 | + eventName: ChangeEventName, |
| 213 | + handler: Function, |
| 214 | + ): {remove: () => void} { |
| 215 | + const listener = connection => { |
| 216 | + if (eventName === 'change') { |
| 217 | + handler(_isConnectedDeprecated(connection)); |
| 218 | + } else if (eventName === 'connectionChange') { |
| 219 | + handler(_isConnected(connection)); |
| 220 | + } |
| 221 | + }; |
| 222 | + _isConnectedSubscriptions.set(handler, listener); |
| 223 | + NetInfo.addEventListener(eventName, listener); |
| 224 | + return { |
| 225 | + remove: () => |
| 226 | + NetInfo.isConnected.removeEventListener(eventName, handler), |
| 227 | + }; |
| 228 | + }, |
| 229 | + |
| 230 | + removeEventListener(eventName: ChangeEventName, handler: Function): void { |
| 231 | + const listener = _isConnectedSubscriptions.get(handler); |
| 232 | + NetInfo.removeEventListener( |
| 233 | + eventName, |
| 234 | + /* $FlowFixMe(>=0.36.0 site=react_native_fb,react_native_oss) Flow error |
| 235 | + * detected during the deploy of Flow v0.36.0. To see the error, remove |
| 236 | + * this comment and run Flow */ |
| 237 | + listener, |
| 238 | + ); |
| 239 | + _isConnectedSubscriptions.delete(handler); |
| 240 | + }, |
| 241 | + |
| 242 | + fetch(): Promise<any> { |
| 243 | + return NetInfo.getConnectionInfo().then(_isConnected); |
| 244 | + }, |
| 245 | + }, |
| 246 | + |
| 247 | + isConnectionExpensive(): Promise<boolean> { |
| 248 | + return Platform.OS === 'android' |
| 249 | + ? RCTNetInfo.isConnectionMetered() |
| 250 | + : Promise.reject(new Error('Currently not supported on iOS')); |
| 251 | + }, |
| 252 | +}; |
| 253 | + |
| 254 | +module.exports = NetInfo; |
0 commit comments