diff --git a/Examples/UIExplorer/NetInfoExample.js b/Examples/UIExplorer/NetInfoExample.js index c322a743228..6ab1805dfee 100644 --- a/Examples/UIExplorer/NetInfoExample.js +++ b/Examples/UIExplorer/NetInfoExample.js @@ -29,13 +29,13 @@ var ReachabilitySubscription = React.createClass({ }; }, componentDidMount: function() { - NetInfo.reachabilityIOS.addEventListener( + NetInfo.addEventListener( 'change', this._handleReachabilityChange ); }, componentWillUnmount: function() { - NetInfo.reachabilityIOS.removeEventListener( + NetInfo.removeEventListener( 'change', this._handleReachabilityChange ); @@ -63,16 +63,16 @@ var ReachabilityCurrent = React.createClass({ }; }, componentDidMount: function() { - NetInfo.reachabilityIOS.addEventListener( + NetInfo.addEventListener( 'change', this._handleReachabilityChange ); - NetInfo.reachabilityIOS.fetch().done( + NetInfo.fetch().done( (reachability) => { this.setState({reachability}); } ); }, componentWillUnmount: function() { - NetInfo.reachabilityIOS.removeEventListener( + NetInfo.removeEventListener( 'change', this._handleReachabilityChange ); diff --git a/Libraries/Network/NetInfo.js b/Libraries/Network/NetInfo.js index 2b65671a9c3..47184d1819b 100644 --- a/Libraries/Network/NetInfo.js +++ b/Libraries/Network/NetInfo.js @@ -12,8 +12,14 @@ 'use strict'; var NativeModules = require('NativeModules'); +var Platform = require('Platform'); var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter'); -var RCTReachability = NativeModules.Reachability; + +if (Platform.OS === 'ios') { + var RCTNetInfo = NativeModules.Reachability; +} else if (Platform.OS === 'android') { + var RCTNetInfo = NativeModules.NetInfo; +} var DEVICE_REACHABILITY_EVENT = 'reachabilityDidChange'; @@ -28,11 +34,50 @@ type ReachabilityStateIOS = $Enum<{ wifi: string; }>; +type ConnectivityStateAndroid = $Enum<{ + NONE: string; + MOBILE: string; + WIFI: string; + MOBILE_MMS: string; + MOBILE_SUPL: string; + MOBILE_DUN: string; + MOBILE_HIPRI: string; + WIMAX: string; + BLUETOOTH: string; + DUMMY: string; + ETHERNET: string; + MOBILE_FOTA: string; + MOBILE_IMS: string; + MOBILE_CBS: string; + WIFI_P2P: string; + MOBILE_IA: string; + MOBILE_EMERGENCY: string; + PROXY: string; + VPN: string; + UNKNOWN: string; +}>; /** * NetInfo exposes info about online/offline status * - * ### reachabilityIOS + * ``` + * NetInfo.fetch().done((reach) => { + * console.log('Initial: ' + reach); + * }); + * function handleFirstConnectivityChange(reach) { + * console.log('First change: ' + reach); + * NetInfo.removeEventListener( + * 'change', + * handleFirstConnectivityChange + * ); + * } + * NetInfo.addEventListener( + * 'change', + * handleFirstConnectivityChange + * ); + * ``` + * + * ### IOS * * Asynchronously determine if the device is online and on a cellular network. * @@ -41,21 +86,35 @@ type ReachabilityStateIOS = $Enum<{ * - `cell` - device is connected via Edge, 3G, WiMax, or LTE * - `unknown` - error case and the network status is unknown * - * ``` - * NetInfo.reachabilityIOS.fetch().done((reach) => { - * console.log('Initial: ' + reach); + * ### Android + * + * Asynchronously determine if the device is connected and details about that connection. + * + * Android Connectivity Types + * - `NONE` - device is offline + * - `BLUETOOTH` - The Bluetooth data connection. + * - `DUMMY` - Dummy data connection. + * - `ETHERNET` - The Ethernet data connection. + * - `MOBILE` - The Mobile data connection. + * - `MOBILE_DUN` - A DUN-specific Mobile data connection. + * - `MOBILE_HIPRI` - A High Priority Mobile data connection. + * - `MOBILE_MMS` - An MMS-specific Mobile data connection. + * - `MOBILE_SUPL` - A SUPL-specific Mobile data connection. + * - `VPN` - A virtual network using one or more native bearers. Requires API Level 21 + * - `WIFI` - The WIFI data connection. + * - `WIMAX` - The WiMAX data connection. + * - `UNKNOWN` - Unknown data connection. + * The rest ConnectivityStates are hidden by the Android API, but can be used if necessary. + * + * ### isConnectionMetered + * + * Available on Android. Detect if the current active connection is metered or not. A network is + * classified as metered when the user is sensitive to heavy data usage on that connection due to + * monetary costs, data limitations or battery/performance issues. + * + * NetInfo.isConnectionMetered((isConnectionMetered) => { + * console.log('Connection is ' + (isConnectionMetered ? 'Metered' : 'Not Metered')); * }); - * function handleFirstReachabilityChange(reach) { - * console.log('First change: ' + reach); - * NetInfo.reachabilityIOS.removeEventListener( - * 'change', - * handleFirstReachabilityChange - * ); - * } - * NetInfo.reachabilityIOS.addEventListener( - * 'change', - * handleFirstReachabilityChange - * ); * ``` * * ### isConnected @@ -81,89 +140,101 @@ type ReachabilityStateIOS = $Enum<{ * ``` */ -var NetInfo = {}; +var _subscriptions = {}; -if (RCTReachability) { - - // RCTReachability is exposed, so this is an iOS-like environment and we will - // expose reachabilityIOS - - var _reachabilitySubscriptions = {}; - - NetInfo.reachabilityIOS = { - addEventListener: function ( - eventName: ChangeEventName, - handler: Function - ): void { - _reachabilitySubscriptions[handler] = RCTDeviceEventEmitter.addListener( - DEVICE_REACHABILITY_EVENT, - (appStateData) => { - handler(appStateData.network_reachability); - } - ); - }, - - removeEventListener: function( - eventName: ChangeEventName, - handler: Function - ): void { - if (!_reachabilitySubscriptions[handler]) { - return; +var NetInfo = { + addEventListener: function ( + eventName: ChangeEventName, + handler: Function + ): void { + _subscriptions[handler] = RCTDeviceEventEmitter.addListener( + DEVICE_REACHABILITY_EVENT, + (appStateData) => { + handler(appStateData.network_reachability); } - _reachabilitySubscriptions[handler].remove(); - _reachabilitySubscriptions[handler] = null; - }, + ); + }, - fetch: function(): Promise { - return new Promise((resolve, reject) => { - RCTReachability.getCurrentReachability( - function(resp) { - resolve(resp.network_reachability); - }, - reject - ); - }); - }, - }; + removeEventListener: function( + eventName: ChangeEventName, + handler: Function + ): void { + if (!_subscriptions[handler]) { + return; + } + _subscriptions[handler].remove(); + _subscriptions[handler] = null; + }, - var _isConnectedSubscriptions = {}; + fetch: function(): Promise { + return new Promise((resolve, reject) => { + RCTNetInfo.getCurrentReachability( + function(resp) { + resolve(resp.network_reachability); + }, + reject + ); + }); + }, - var _iosReachabilityIsConnected = function( + isConnected: {}, + + isConnectionMetered: {}, +}; + +if (Platform.OS === 'ios') { + var _isConnected = function( reachability: ReachabilityStateIOS ): bool { return reachability !== 'none' && reachability !== 'unknown'; }; +} else if (Platform.OS === 'android') { + var _isConnected = function( + connectionType: ConnectivityStateAndroid + ): bool { + return connectionType !== 'NONE' && connectionType !== 'UNKNOWN'; + }; +} - NetInfo.isConnected = { - addEventListener: function ( - eventName: ChangeEventName, - handler: Function - ): void { - _isConnectedSubscriptions[handler] = (reachability) => { - handler(_iosReachabilityIsConnected(reachability)); - }; - NetInfo.reachabilityIOS.addEventListener( - eventName, - _isConnectedSubscriptions[handler] - ); - }, +var _isConnectedSubscriptions = {}; - removeEventListener: function( - eventName: ChangeEventName, - handler: Function - ): void { - NetInfo.reachabilityIOS.removeEventListener( - eventName, - _isConnectedSubscriptions[handler] - ); - }, +NetInfo.isConnected = { + addEventListener: function ( + eventName: ChangeEventName, + handler: Function + ): void { + _isConnectedSubscriptions[handler] = (connection) => { + handler(_isConnected(connection)); + }; + NetInfo.addEventListener( + eventName, + _isConnectedSubscriptions[handler] + ); + }, - fetch: function(): Promise { - return NetInfo.reachabilityIOS.fetch().then( - (reachability) => _iosReachabilityIsConnected(reachability) - ); - }, + removeEventListener: function( + eventName: ChangeEventName, + handler: Function + ): void { + NetInfo.removeEventListener( + eventName, + _isConnectedSubscriptions[handler] + ); + }, + + fetch: function(): Promise { + return NetInfo.fetch().then( + (connection) => _isConnected(connection) + ); + }, +}; + +if (Platform.OS === 'android') { + NetInfo.isConnectionMetered = function(callback): void { + RCTNetInfo.isConnectionMetered((_isMetered) => { + callback(_isMetered); + }); }; }