Skip to content

Commit 0aa2486

Browse files
Gretzkymatt-oakes
authored andcommitted
feat: Add additional details for cellular and wifi connections (#122 by @Gretzky)
* For `cellular` connections, add `carrier` on Android and iOS * For `wifi` connections, add `ssid` and `strength` for Android and `ipAddress` for Android and iOS
1 parent ed4a2cf commit 0aa2486

File tree

6 files changed

+149
-10
lines changed

6 files changed

+149
-10
lines changed

README.md

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -183,22 +183,34 @@ The `details` value depends on the `type` value.
183183

184184
`details` is `null`.
185185

186-
##### `type` is `wifi`, `bluetooth`, `ethernet`, `wimax`, `vpn`, or `other`
186+
##### `type` is `wifi`
187187

188188
`details` has these properties:
189189

190-
| Property | Type | Description |
191-
| ----------------------- | --------- | ------------------------------------------------------------------------------------------------------ |
192-
| `isConnectionExpensive` | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
190+
| Property | Platform | Type | Description |
191+
| ----------------------- | --------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
192+
| `isConnectionExpensive` | Android, iOS, Windows | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
193+
| `ssid` | Android | `string` | The SSID of the network. May not be present, `null`, or an empty string if it cannot be determined. |
194+
| `strength` | Android | `number` | An integer number from `0` to `5` for the signal strength. May not be present if the signal strength cannot be determined. |
195+
| `ipAddress` | Android, iOS | `string` | The external IP address. Can be in IPv4 or IPv6 format. May not be present if it cannot be determined. |
193196

194197
##### `type` is `cellular`
195198

196199
`details` has these properties:
197200

198-
| Property | Type | Description |
199-
| ----------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
200-
| `isConnectionExpensive` | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
201-
| `cellularGeneration` | [`NetInfoCellularGeneration`](#netinfocellulargeneration) | The generation of the cell network the user is connected to. This can give an indication of speed, but no guarantees. |
201+
| Property | Platform | Type | Description |
202+
| ----------------------- | --------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
203+
| `isConnectionExpensive` | Android, iOS, Windows | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
204+
| `cellularGeneration` | Android, iOS, Windows | [`NetInfoCellularGeneration`](#netinfocellulargeneration) | The generation of the cell network the user is connected to. This can give an indication of speed, but no guarantees. |
205+
| `carrier` | Android, iOS | `string` | The network carrier name. May not be present or may be empty if none can be determined. |
206+
207+
##### `type` is `bluetooth`, `ethernet`, `wimax`, `vpn`, or `other`
208+
209+
`details` has these properties:
210+
211+
| Property | Type | Description |
212+
| ----------------------- | --------- | ------------------------------------------------------------------------------------------------------ |
213+
| `isConnectionExpensive` | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
202214

203215
#### `NetInfoStateType`
204216
Describes the current type of network connection. It is an enum with these possible values:

android/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
<uses-permission
77
android:name="android.permission.ACCESS_NETWORK_STATE" />
8+
<uses-permission
9+
android:name="android.permission.ACCESS_WIFI_STATE" />
810

911
</manifest>
1012

android/src/main/java/com/reactnativecommunity/netinfo/ConnectivityReceiver.java

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
import android.content.Context;
1010
import android.net.ConnectivityManager;
11+
import android.net.wifi.WifiInfo;
12+
import android.net.wifi.WifiManager;
13+
import android.telephony.TelephonyManager;
1114
import androidx.core.net.ConnectivityManagerCompat;
1215
import com.facebook.react.bridge.Promise;
1316
import com.facebook.react.bridge.ReactApplicationContext;
@@ -16,12 +19,16 @@
1619
import com.facebook.react.modules.core.DeviceEventManagerModule;
1720
import com.reactnativecommunity.netinfo.types.CellularGeneration;
1821
import com.reactnativecommunity.netinfo.types.ConnectionType;
22+
import java.math.BigInteger;
23+
import java.net.InetAddress;
1924
import javax.annotation.Nonnull;
2025
import javax.annotation.Nullable;
2126

2227
abstract class ConnectivityReceiver {
2328

2429
private final ConnectivityManager mConnectivityManager;
30+
private final WifiManager mWifiManager;
31+
private final TelephonyManager mTelephonyManager;
2532
private final ReactApplicationContext mReactContext;
2633

2734
@Nonnull private ConnectionType mConnectionType = ConnectionType.UNKNOWN;
@@ -32,6 +39,11 @@ abstract class ConnectivityReceiver {
3239
mReactContext = reactContext;
3340
mConnectivityManager =
3441
(ConnectivityManager) reactContext.getSystemService(Context.CONNECTIVITY_SERVICE);
42+
mWifiManager =
43+
(WifiManager)
44+
reactContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
45+
mTelephonyManager =
46+
(TelephonyManager) reactContext.getSystemService(Context.TELEPHONY_SERVICE);
3547
}
3648

3749
abstract void register();
@@ -98,8 +110,54 @@ private WritableMap createConnectivityEventMap() {
98110
ConnectivityManagerCompat.isActiveNetworkMetered(getConnectivityManager());
99111
details.putBoolean("isConnectionExpensive", isConnectionExpensive);
100112

101-
if (mConnectionType.equals(ConnectionType.CELLULAR) && mCellularGeneration != null) {
102-
details.putString("cellularGeneration", mCellularGeneration.label);
113+
if (mConnectionType.equals(ConnectionType.CELLULAR)) {
114+
// Add the cellular generation, if we have one
115+
if (mCellularGeneration != null) {
116+
details.putString("cellularGeneration", mCellularGeneration.label);
117+
}
118+
119+
// Add the network operator name, if there is one
120+
String carrier = mTelephonyManager.getNetworkOperatorName();
121+
if (carrier != null) {
122+
details.putString("carrier", carrier);
123+
}
124+
} else if (mConnectionType.equals(ConnectionType.WIFI)) {
125+
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
126+
127+
if (wifiInfo != null) {
128+
// Get the SSID
129+
try {
130+
String initialSSID = wifiInfo.getSSID();
131+
if (initialSSID != null && !initialSSID.contains("<unknown ssid>")) {
132+
// Strip the quotes, if any
133+
String ssid = initialSSID.replace("\"", "");
134+
details.putString("ssid", ssid);
135+
}
136+
} catch (Exception e) {
137+
// Ignore errors
138+
}
139+
140+
// Get/parse the wifi signal strength
141+
try {
142+
int signalStrength =
143+
WifiManager.calculateSignalLevel(wifiInfo.getRssi(), 100);
144+
details.putInt("strength", signalStrength);
145+
} catch (Exception e) {
146+
// Ignore errors
147+
}
148+
149+
// Get the IP address
150+
try {
151+
byte[] ipAddressByteArray =
152+
BigInteger.valueOf(wifiInfo.getIpAddress()).toByteArray();
153+
NetInfoUtils.reverseByteArray(ipAddressByteArray);
154+
InetAddress inetAddress = InetAddress.getByAddress(ipAddressByteArray);
155+
String ipAddress = inetAddress.getHostAddress();
156+
details.putString("ipAddress", ipAddress);
157+
} catch (Exception e) {
158+
// Ignore errors
159+
}
160+
}
103161
}
104162
}
105163
event.putMap("details", details);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
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+
package com.reactnativecommunity.netinfo;
8+
9+
public class NetInfoUtils {
10+
public static void reverseByteArray(byte[] array) {
11+
for (int i = 0; i < array.length / 2; i++) {
12+
byte temp = array[i];
13+
array[i] = array[array.length - i - 1];
14+
array[array.length - i - 1] = temp;
15+
}
16+
}
17+
}

ios/RNCNetInfo.m

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
#import "RNCNetInfo.h"
99
#import "RNCConnectionStateWatcher.h"
1010

11+
#include <ifaddrs.h>
12+
#include <arpa/inet.h>
13+
@import CoreTelephony;
14+
1115
#import <React/RCTAssert.h>
1216
#import <React/RCTBridge.h>
1317
#import <React/RCTEventDispatcher.h>
@@ -99,6 +103,9 @@ - (NSDictionary *)currentDictionaryFromUpdateState:(RNCConnectionState *)state
99103

100104
if ([state.type isEqualToString:RNCConnectionTypeCellular]) {
101105
details[@"cellularGeneration"] = state.cellularGeneration ?: NSNull.null;
106+
details[@"carrier"] = [self carrier] ?: NSNull.null;
107+
} else if ([state.type isEqualToString:RNCConnectionTypeWifi]) {
108+
details[@"ipAddress"] = [self ipAddress] ?: NSNull.null;
102109
}
103110
}
104111

@@ -109,4 +116,43 @@ - (NSDictionary *)currentDictionaryFromUpdateState:(RNCConnectionState *)state
109116
};
110117
}
111118

119+
- (NSString *)carrier
120+
{
121+
#if (TARGET_OS_TV)
122+
return nil;
123+
#else
124+
CTTelephonyNetworkInfo *netinfo = [[CTTelephonyNetworkInfo alloc] init];
125+
CTCarrier *carrier = [netinfo subscriberCellularProvider];
126+
return carrier.carrierName;
127+
#endif
128+
}
129+
130+
- (NSString *)ipAddress
131+
{
132+
NSString *address = @"0.0.0.0";
133+
struct ifaddrs *interfaces = NULL;
134+
struct ifaddrs *temp_addr = NULL;
135+
int success = 0;
136+
// retrieve the current interfaces - returns 0 on success
137+
success = getifaddrs(&interfaces);
138+
if (success == 0) {
139+
// Loop through linked list of interfaces
140+
temp_addr = interfaces;
141+
while (temp_addr != NULL) {
142+
if (temp_addr->ifa_addr->sa_family == AF_INET) {
143+
// Check if interface is en0 which is the wifi connection on the iPhone
144+
if ([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
145+
// Get NSString from C String
146+
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
147+
}
148+
}
149+
150+
temp_addr = temp_addr->ifa_next;
151+
}
152+
}
153+
// Free memory
154+
freeifaddrs(interfaces);
155+
return address;
156+
}
157+
112158
@end

ios/RNCNetInfo.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
C9B8547F229A6175003B9CCA /* RNCConnectionStateWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = C9B8547D229A6175003B9CCA /* RNCConnectionStateWatcher.m */; };
1616
C9B85482229A669E003B9CCA /* RNCConnectionState.m in Sources */ = {isa = PBXBuildFile; fileRef = C9B85481229A669E003B9CCA /* RNCConnectionState.m */; };
1717
C9B85483229A669E003B9CCA /* RNCConnectionState.m in Sources */ = {isa = PBXBuildFile; fileRef = C9B85481229A669E003B9CCA /* RNCConnectionState.m */; };
18+
C9CB7A5A231E1CE8000393F8 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9CB7A59231E1CE8000393F8 /* CoreTelephony.framework */; };
1819
/* End PBXBuildFile section */
1920

2021
/* Begin PBXCopyFilesBuildPhase section */
@@ -48,13 +49,15 @@
4849
C9B8547D229A6175003B9CCA /* RNCConnectionStateWatcher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCConnectionStateWatcher.m; sourceTree = "<group>"; };
4950
C9B85480229A669E003B9CCA /* RNCConnectionState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCConnectionState.h; sourceTree = "<group>"; };
5051
C9B85481229A669E003B9CCA /* RNCConnectionState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCConnectionState.m; sourceTree = "<group>"; };
52+
C9CB7A59231E1CE8000393F8 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; };
5153
/* End PBXFileReference section */
5254

5355
/* Begin PBXFrameworksBuildPhase section */
5456
58B511D81A9E6C8500147676 /* Frameworks */ = {
5557
isa = PBXFrameworksBuildPhase;
5658
buildActionMask = 2147483647;
5759
files = (
60+
C9CB7A5A231E1CE8000393F8 /* CoreTelephony.framework in Frameworks */,
5861
C923EDBC220C2C1A00D3100F /* SystemConfiguration.framework in Frameworks */,
5962
);
6063
runOnlyForDeploymentPostprocessing = 0;
@@ -96,6 +99,7 @@
9699
C923EDBA220C2C1A00D3100F /* Frameworks */ = {
97100
isa = PBXGroup;
98101
children = (
102+
C9CB7A59231E1CE8000393F8 /* CoreTelephony.framework */,
99103
C923EDBB220C2C1A00D3100F /* SystemConfiguration.framework */,
100104
);
101105
name = Frameworks;

0 commit comments

Comments
 (0)