expo-network 5.0.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,18 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 5.2.0 — 2023-02-03
14
+
15
+ ### 💡 Others
16
+
17
+ - On Android bump `compileSdkVersion` and `targetSdkVersion` to `33`. ([#20721](https://github.com/expo/expo/pull/20721) by [@lukmccall](https://github.com/lukmccall))
18
+
19
+ ## 5.1.0 — 2022-12-30
20
+
21
+ ### 🎉 New features
22
+
23
+ - Migrated to Expo Modules API. ([#20083](https://github.com/expo/expo/pull/20083) and [#20303](https://github.com/expo/expo/pull/20303) by [@alanhughes](https://github.com/alanjhughes))
24
+
13
25
  ## 5.0.0 — 2022-10-25
14
26
 
15
27
  ### 🛠 Breaking changes
package/README.md CHANGED
@@ -6,7 +6,7 @@ See [<ModuleName> docs](https://docs.expo.dev/versions/latest/sdk/<module-docs-n
6
6
 
7
7
  # API documentation
8
8
 
9
- - [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/network.md)
9
+ - [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/network.mdx)
10
10
  - [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/network/)
11
11
 
12
12
  # Installation in managed Expo projects
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '5.0.0'
6
+ version = '5.2.0'
7
7
 
8
8
  buildscript {
9
9
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -59,7 +59,7 @@ afterEvaluate {
59
59
  }
60
60
 
61
61
  android {
62
- compileSdkVersion safeExtGet("compileSdkVersion", 31)
62
+ compileSdkVersion safeExtGet("compileSdkVersion", 33)
63
63
 
64
64
  compileOptions {
65
65
  sourceCompatibility JavaVersion.VERSION_11
@@ -72,9 +72,9 @@ android {
72
72
 
73
73
  defaultConfig {
74
74
  minSdkVersion safeExtGet("minSdkVersion", 21)
75
- targetSdkVersion safeExtGet("targetSdkVersion", 31)
75
+ targetSdkVersion safeExtGet("targetSdkVersion", 33)
76
76
  versionCode 11
77
- versionName '5.0.0'
77
+ versionName '5.2.0'
78
78
  }
79
79
  lintOptions {
80
80
  abortOnError false
@@ -0,0 +1,9 @@
1
+ package expo.modules.network
2
+
3
+ import expo.modules.kotlin.exception.CodedException
4
+
5
+ internal class NetworkAccessException(e: Exception) :
6
+ CodedException("Unable to access network information", e.cause)
7
+
8
+ internal class NetworkWifiException(e: Exception) :
9
+ CodedException("Wi-Fi information could not be acquired", e.cause)
@@ -1,31 +1,80 @@
1
1
  package expo.modules.network
2
2
 
3
- import expo.modules.core.Promise
4
- import expo.modules.core.ExportedModule
5
- import expo.modules.core.interfaces.ExpoMethod
6
- import expo.modules.core.interfaces.RegistryLifecycleListener
7
-
8
- import android.util.Log
9
- import android.os.Build
10
- import android.os.Bundle
11
3
  import android.content.Context
4
+ import android.net.ConnectivityManager
5
+ import android.net.NetworkCapabilities
12
6
  import android.net.NetworkInfo
13
7
  import android.net.wifi.WifiInfo
14
8
  import android.net.wifi.WifiManager
15
- import android.net.ConnectivityManager
16
- import android.net.NetworkCapabilities
9
+ import android.os.Build
10
+ import android.os.Bundle
17
11
  import android.provider.Settings
18
-
19
- import java.lang.Exception
12
+ import android.util.Log
13
+ import expo.modules.kotlin.Promise
14
+ import expo.modules.kotlin.exception.Exceptions
15
+ import expo.modules.kotlin.modules.Module
16
+ import expo.modules.kotlin.modules.ModuleDefinition
20
17
  import java.math.BigInteger
21
18
  import java.net.InetAddress
22
19
  import java.net.UnknownHostException
23
20
  import java.nio.ByteOrder
24
21
 
25
- private const val NAME = "ExpoNetwork"
26
22
  private val TAG = NetworkModule::class.java.simpleName
27
23
 
28
- class NetworkModule(private val appContext: Context) : ExportedModule(appContext), RegistryLifecycleListener {
24
+ class NetworkModule : Module() {
25
+ private val context: Context
26
+ get() = appContext.reactContext ?: throw Exceptions.ReactContextLost()
27
+
28
+ override fun definition() = ModuleDefinition {
29
+ Name("ExpoNetwork")
30
+
31
+ AsyncFunction("getNetworkStateAsync") { promise: Promise ->
32
+ val result = Bundle()
33
+ val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
34
+
35
+ try {
36
+ if (Build.VERSION.SDK_INT < 29) { // use getActiveNetworkInfo before api level 29
37
+ val netInfo = connectivityManager.activeNetworkInfo
38
+ val connectionType = getConnectionType(netInfo)
39
+
40
+ result.apply {
41
+ putBoolean("isInternetReachable", netInfo!!.isConnected)
42
+ putString("type", connectionType.value)
43
+ putBoolean("isConnected", connectionType.isDefined)
44
+ }
45
+
46
+ promise.resolve(result)
47
+ } else {
48
+ val network = connectivityManager.activeNetwork
49
+ val isInternetReachable = network != null
50
+
51
+ val connectionType = if (isInternetReachable) {
52
+ val netCapabilities = connectivityManager.getNetworkCapabilities(network)
53
+ getConnectionType(netCapabilities)
54
+ } else {
55
+ null
56
+ }
57
+
58
+ result.apply {
59
+ putString("type", connectionType?.value ?: NetworkStateType.NONE.value)
60
+ putBoolean("isInternetReachable", isInternetReachable)
61
+ putBoolean("isConnected", connectionType != null && connectionType.isDefined)
62
+ }
63
+ promise.resolve(result)
64
+ }
65
+ } catch (e: Exception) {
66
+ throw NetworkAccessException(e)
67
+ }
68
+ }
69
+
70
+ AsyncFunction("getIpAddressAsync") {
71
+ return@AsyncFunction rawIpToString(wifiInfo.ipAddress)
72
+ }
73
+
74
+ AsyncFunction("isAirplaneModeEnabledAsync") {
75
+ return@AsyncFunction Settings.Global.getInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0) != 0
76
+ }
77
+ }
29
78
 
30
79
  enum class NetworkStateType(val value: String) {
31
80
  NONE("NONE"),
@@ -42,15 +91,13 @@ class NetworkModule(private val appContext: Context) : ExportedModule(appContext
42
91
  get() = this.value != "NONE" && this.value != "UNKNOWN"
43
92
  }
44
93
 
45
- override fun getName() = NAME
46
-
47
94
  private val wifiInfo: WifiInfo
48
95
  get() = try {
49
- val manager = appContext.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
96
+ val manager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
50
97
  manager.connectionInfo
51
98
  } catch (e: Exception) {
52
99
  Log.e(TAG, e.message ?: "Wi-Fi information could not be acquired")
53
- throw e
100
+ throw NetworkWifiException(e)
54
101
  }
55
102
 
56
103
  private fun getConnectionType(netInfo: NetworkInfo?): NetworkStateType = when (netInfo?.type) {
@@ -75,12 +122,12 @@ class NetworkModule(private val appContext: Context) : ExportedModule(appContext
75
122
  else -> NetworkStateType.UNKNOWN
76
123
  }
77
124
 
78
- private fun rawIpToString(ip: Int): String {
125
+ private fun rawIpToString(ipAddress: Int): String {
79
126
  // Convert little-endian to big-endian if needed
80
127
  val ip = if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
81
- Integer.reverseBytes(ip)
128
+ Integer.reverseBytes(ipAddress)
82
129
  } else {
83
- ip
130
+ ipAddress
84
131
  }
85
132
 
86
133
  var ipByteArray = BigInteger.valueOf(ip.toLong()).toByteArray()
@@ -89,66 +136,9 @@ class NetworkModule(private val appContext: Context) : ExportedModule(appContext
89
136
  }
90
137
 
91
138
  return try {
92
- InetAddress.getByAddress(ipByteArray).hostAddress
139
+ InetAddress.getByAddress(ipByteArray).hostAddress as String
93
140
  } catch (e: UnknownHostException) {
94
141
  "0.0.0.0"
95
142
  }
96
143
  }
97
-
98
- @ExpoMethod
99
- fun getNetworkStateAsync(promise: Promise) {
100
- val result = Bundle()
101
- val connectivityManager = appContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
102
-
103
- try {
104
- if (Build.VERSION.SDK_INT < 29) { // use getActiveNetworkInfo before api level 29
105
- val netInfo = connectivityManager.activeNetworkInfo
106
- val connectionType = getConnectionType(netInfo)
107
-
108
- result.apply {
109
- putBoolean("isInternetReachable", netInfo!!.isConnected)
110
- putString("type", connectionType.value)
111
- putBoolean("isConnected", connectionType.isDefined)
112
- }
113
-
114
- promise.resolve(result)
115
- } else {
116
- val network = connectivityManager.activeNetwork
117
- val isInternetReachable = network != null
118
-
119
- val connectionType = if (isInternetReachable) {
120
- val netCapabilities = connectivityManager.getNetworkCapabilities(network)
121
- getConnectionType(netCapabilities)
122
- } else {
123
- null
124
- }
125
-
126
- result.apply {
127
- putString("type", connectionType?.value ?: NetworkStateType.NONE.value)
128
- putBoolean("isInternetReachable", isInternetReachable)
129
- putBoolean("isConnected", connectionType != null && connectionType.isDefined)
130
- }
131
-
132
- promise.resolve(result)
133
- }
134
- } catch (e: Exception) {
135
- promise.reject("ERR_NETWORK_NO_ACCESS_NETWORKINFO", "Unable to access network information", e)
136
- }
137
- }
138
-
139
- @ExpoMethod
140
- fun getIpAddressAsync(promise: Promise) {
141
- try {
142
- promise.resolve(rawIpToString(wifiInfo.ipAddress))
143
- } catch (e: Exception) {
144
- Log.e(TAG, e.message ?: "Could not get IP address")
145
- promise.reject("ERR_NETWORK_IP_ADDRESS", "Unknown Host Exception", e)
146
- }
147
- }
148
-
149
- @ExpoMethod
150
- fun isAirplaneModeEnabledAsync(promise: Promise) {
151
- val isAirplaneMode = Settings.Global.getInt(appContext.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0) != 0
152
- promise.resolve(isAirplaneMode)
153
- }
154
144
  }
@@ -1,3 +1,3 @@
1
- declare const _default: import("expo-modules-core").ProxyNativeModule;
1
+ declare const _default: any;
2
2
  export default _default;
3
3
  //# sourceMappingURL=ExpoNetwork.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoNetwork.d.ts","sourceRoot":"","sources":["../src/ExpoNetwork.ts"],"names":[],"mappings":";AACA,wBAA8C"}
1
+ {"version":3,"file":"ExpoNetwork.d.ts","sourceRoot":"","sources":["../src/ExpoNetwork.ts"],"names":[],"mappings":";AACA,wBAAkD"}
@@ -1,3 +1,3 @@
1
- import { NativeModulesProxy } from 'expo-modules-core';
2
- export default NativeModulesProxy.ExpoNetwork;
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ export default requireNativeModule('ExpoNetwork');
3
3
  //# sourceMappingURL=ExpoNetwork.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoNetwork.js","sourceRoot":"","sources":["../src/ExpoNetwork.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,eAAe,kBAAkB,CAAC,WAAW,CAAC","sourcesContent":["import { NativeModulesProxy } from 'expo-modules-core';\nexport default NativeModulesProxy.ExpoNetwork;\n"]}
1
+ {"version":3,"file":"ExpoNetwork.js","sourceRoot":"","sources":["../src/ExpoNetwork.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,eAAe,mBAAmB,CAAC,aAAa,CAAC,CAAC","sourcesContent":["import { requireNativeModule } from 'expo-modules-core';\nexport default requireNativeModule('ExpoNetwork');\n"]}
@@ -1,4 +1,4 @@
1
- export declare type NetworkState = {
1
+ export type NetworkState = {
2
2
  /**
3
3
  * A [`NetworkStateType`](#networkstatetype) enum value that represents the current network
4
4
  * connection type.
@@ -1 +1 @@
1
- {"version":3,"file":"Network.types.d.ts","sourceRoot":"","sources":["../src/Network.types.ts"],"names":[],"mappings":"AACA,oBAAY,YAAY,GAAG;IACzB;;;OAGG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAGF;;GAEG;AACH,oBAAY,gBAAgB;IAC1B;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,OAAO,YAAY;IACnB;;;OAGG;IACH,QAAQ,aAAa;IACrB;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,SAAS,cAAc;IACvB;;OAEG;IACH,QAAQ,aAAa;IACrB;;OAEG;IACH,KAAK,UAAU;IACf;;OAEG;IACH,GAAG,QAAQ;IACX;;OAEG;IACH,KAAK,UAAU;CAChB"}
1
+ {"version":3,"file":"Network.types.d.ts","sourceRoot":"","sources":["../src/Network.types.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,YAAY,GAAG;IACzB;;;OAGG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAGF;;GAEG;AACH,oBAAY,gBAAgB;IAC1B;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,OAAO,YAAY;IACnB;;;OAGG;IACH,QAAQ,aAAa;IACrB;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,SAAS,cAAc;IACvB;;OAEG;IACH,QAAQ,aAAa;IACrB;;OAEG;IACH,KAAK,UAAU;IACf;;OAEG;IACH,GAAG,QAAQ;IACX;;OAEG;IACH,KAAK,UAAU;CAChB"}
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "expo-network",
3
+ "platforms": ["ios", "android", "web"],
4
+ "ios": {
5
+ "modules": ["NetworkModule"]
6
+ },
7
+ "android": {
8
+ "modules": ["expo.modules.network.NetworkModule"]
9
+ }
10
+ }
@@ -0,0 +1,7 @@
1
+ import ExpoModulesCore
2
+
3
+ internal class IpAddressException: GenericException<Int32> {
4
+ override var reason: String {
5
+ "No network interfaces could be retrieved. getifaddrs() failed with error number: \(param)"
6
+ }
7
+ }
@@ -3,7 +3,7 @@ require 'json'
3
3
  package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
4
4
 
5
5
  Pod::Spec.new do |s|
6
- s.name = 'EXNetwork'
6
+ s.name = 'ExpoNetwork'
7
7
  s.version = package['version']
8
8
  s.summary = package['description']
9
9
  s.description = package['description']
@@ -15,11 +15,17 @@ Pod::Spec.new do |s|
15
15
  s.static_framework = true
16
16
 
17
17
  s.dependency 'ExpoModulesCore'
18
+
19
+ # Swift/Objective-C compatibility
20
+ s.pod_target_xcconfig = {
21
+ 'DEFINES_MODULE' => 'YES',
22
+ 'SWIFT_COMPILATION_MODE' => 'wholemodule'
23
+ }
18
24
 
19
25
  if !$ExpoUseSources&.include?(package['name']) && ENV['EXPO_USE_SOURCE'].to_i == 0 && File.exist?("#{s.name}.xcframework") && Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.10.0')
20
- s.source_files = "#{s.name}/**/*.h"
26
+ s.source_files = "**/*.h"
21
27
  s.vendored_frameworks = "#{s.name}.xcframework"
22
28
  else
23
- s.source_files = "#{s.name}/**/*.{h,m}"
29
+ s.source_files = "**/*.{h,m,swift}"
24
30
  end
25
31
  end
@@ -0,0 +1,102 @@
1
+ import ExpoModulesCore
2
+ import SystemConfiguration
3
+ import Network
4
+
5
+ public final class NetworkModule: Module {
6
+ private let monitor = NWPathMonitor()
7
+ private let monitorQueue = DispatchQueue.global(qos: .default)
8
+
9
+ public func definition() -> ModuleDefinition {
10
+ Name("ExpoNetwork")
11
+
12
+ OnCreate {
13
+ monitor.start(queue: monitorQueue)
14
+ }
15
+
16
+ AsyncFunction("getIpAddressAsync") { () -> String? in
17
+ return try getIPAddress()
18
+ }
19
+
20
+ AsyncFunction("getNetworkStateAsync") {
21
+ return getNetworkStateAsync()
22
+ }
23
+
24
+ OnDestroy {
25
+ monitor.cancel()
26
+ }
27
+ }
28
+
29
+ private func getIPAddress() throws -> String {
30
+ var address = "0.0.0.0"
31
+ var ifaddr: UnsafeMutablePointer<ifaddrs>?
32
+
33
+ let error = getifaddrs(&ifaddr)
34
+
35
+ guard error == 0 else {
36
+ throw IpAddressException(error)
37
+ }
38
+
39
+ guard let firstAddr = ifaddr else {
40
+ return address
41
+ }
42
+
43
+ for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
44
+ let temp = ifptr.pointee
45
+ let family = temp.ifa_addr.pointee.sa_family
46
+
47
+ if family == UInt8(AF_INET) {
48
+ let name = String(cString: temp.ifa_name)
49
+ if name == "en0" || name == "en1" {
50
+ var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
51
+ getnameinfo(
52
+ temp.ifa_addr,
53
+ socklen_t(temp.ifa_addr.pointee.sa_len),
54
+ &hostname,
55
+ socklen_t(hostname.count),
56
+ nil,
57
+ socklen_t(0),
58
+ NI_NUMERICHOST)
59
+ address = String(cString: hostname)
60
+ }
61
+ }
62
+ }
63
+
64
+ freeifaddrs(ifaddr)
65
+ return address
66
+ }
67
+
68
+ private func getNetworkStateAsync() -> [String: Any] {
69
+ let path = monitor.currentPath
70
+ let isConnected = path.status == .satisfied
71
+ var currentNetworkType = NetworkType.unknown
72
+
73
+ if !isConnected {
74
+ return [
75
+ "type": NetworkType.none.description,
76
+ "isConnected": isConnected,
77
+ "isInternetReachable": isConnected
78
+ ]
79
+ }
80
+
81
+ let connectionType = NWInterface
82
+ .InterfaceType
83
+ .allCases
84
+ .filter { path.usesInterfaceType($0) }
85
+ .first
86
+
87
+ switch connectionType {
88
+ case .wifi:
89
+ currentNetworkType = .wifi
90
+ case .cellular:
91
+ currentNetworkType = .cellular
92
+ default:
93
+ currentNetworkType = .unknown
94
+ }
95
+
96
+ return [
97
+ "type": currentNetworkType.description,
98
+ "isConnected": isConnected,
99
+ "isInternetReachable": isConnected
100
+ ]
101
+ }
102
+ }
@@ -0,0 +1,28 @@
1
+ import Network
2
+
3
+ extension NWInterface.InterfaceType: CaseIterable {
4
+ public static var allCases: [NWInterface.InterfaceType] = [
5
+ .other,
6
+ .wifi,
7
+ .cellular,
8
+ .loopback,
9
+ .wiredEthernet
10
+ ]
11
+ }
12
+
13
+ enum NetworkType: CustomStringConvertible {
14
+ case unknown, wifi, none, cellular
15
+
16
+ var description: String {
17
+ switch self {
18
+ case .wifi:
19
+ return "WIFI"
20
+ case .cellular:
21
+ return "CELLULAR"
22
+ case .unknown:
23
+ return "UNKNOWN"
24
+ case .none:
25
+ return "NONE"
26
+ }
27
+ }
28
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-network",
3
- "version": "5.0.0",
3
+ "version": "5.2.0",
4
4
  "description": "Provides useful information about the device's network such as its IP address, MAC address, and airplane mode status",
5
5
  "main": "build/Network.js",
6
6
  "types": "build/Network.d.ts",
@@ -36,5 +36,5 @@
36
36
  "peerDependencies": {
37
37
  "expo": "*"
38
38
  },
39
- "gitHead": "eab2b09c735fb0fc2bf734a3f29a6593adba3838"
39
+ "gitHead": "1815e2eaad8c753588c7b1eb74420174a28e01f4"
40
40
  }
@@ -1,2 +1,2 @@
1
- import { NativeModulesProxy } from 'expo-modules-core';
2
- export default NativeModulesProxy.ExpoNetwork;
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ export default requireNativeModule('ExpoNetwork');
@@ -1,11 +0,0 @@
1
- package expo.modules.network
2
-
3
- import android.content.Context
4
-
5
- import expo.modules.core.BasePackage
6
- import expo.modules.core.ExportedModule
7
-
8
- class NetworkPackage : BasePackage() {
9
- override fun createExportedModules(context: Context): List<ExportedModule> =
10
- listOf(NetworkModule(context))
11
- }
@@ -1,13 +0,0 @@
1
- // Copyright © 2018 650 Industries. All rights reserved.
2
-
3
- #import <ExpoModulesCore/EXExportedModule.h>
4
- #import <ExpoModulesCore/EXModuleRegistryConsumer.h>
5
-
6
- static NSString *const EXNetworkTypeUnknown = @"UNKNOWN";
7
- static NSString *const EXNetworkTypeNone = @"NONE";
8
- static NSString *const EXNetworkTypeWifi = @"WIFI";
9
- static NSString *const EXNetworkTypeCellular = @"CELLULAR";
10
-
11
-
12
- @interface EXNetwork : EXExportedModule <EXModuleRegistryConsumer>
13
- @end
@@ -1,123 +0,0 @@
1
- // Copyright 2018-present 650 Industries. All rights reserved.
2
-
3
- #import <EXNetwork/EXNetwork.h>
4
- #import <SystemConfiguration/SystemConfiguration.h>
5
-
6
- #import <ifaddrs.h>
7
- #import <errno.h>
8
- #import <arpa/inet.h>
9
-
10
- @interface EXNetwork ()
11
-
12
- @property (nonatomic, weak) EXModuleRegistry *moduleRegistry;
13
- @property (nonatomic) SCNetworkReachabilityRef reachabilityRef;
14
- @property (nonatomic) SCNetworkReachabilityFlags lastFlags;
15
- @property (nonatomic) NSString *type;
16
-
17
- @end
18
-
19
- @implementation EXNetwork
20
-
21
- // Creates a new "blank" state
22
- - (instancetype)init
23
- {
24
- self = [super init];
25
- if (self) {
26
- _type = EXNetworkTypeUnknown;
27
- }
28
- return self;
29
- }
30
-
31
- EX_EXPORT_MODULE(ExpoNetwork);
32
-
33
- - (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
34
- {
35
- _moduleRegistry = moduleRegistry;
36
- }
37
-
38
- EX_EXPORT_METHOD_AS(getIpAddressAsync,
39
- getIpAddressAsyncWithResolver:(EXPromiseResolveBlock)resolve rejecter:(EXPromiseRejectBlock)reject)
40
- {
41
- NSString *address = @"0.0.0.0";
42
- struct ifaddrs *interfaces = NULL;
43
- struct ifaddrs *temp_addr = NULL;
44
- int error = 0;
45
- // retrieve the current interfaces - On success, returns 0; on error, -1 is returned, and errno is set appropriately.
46
- error = getifaddrs(&interfaces);
47
-
48
- if (error == 0) {
49
- // Loop through linked list of interfaces
50
- temp_addr = interfaces;
51
- while(temp_addr != NULL) {
52
- if(temp_addr->ifa_addr->sa_family == AF_INET) {
53
- // Check if interface is en0 which is the wifi connection on the iPhone
54
- if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:@"en0"]) {
55
- // Get NSString from C String
56
- address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
57
- }
58
- }
59
- temp_addr = temp_addr->ifa_next;
60
- }
61
- resolve(address);
62
- } else {
63
- NSString *errorMessage = [NSString stringWithFormat:@"%@/%d/%s", @"No network interfaces could be retrieved. getifaddrs() failed with error number: ", errno, strerror(errno)];
64
-
65
- reject(@"ERR_NETWORK_IP_ADDRESS", errorMessage, nil);
66
- }
67
-
68
- // Free memory
69
- freeifaddrs(interfaces);
70
- }
71
-
72
- EX_EXPORT_METHOD_AS(getNetworkStateAsync,
73
- getNetworkStateAsyncWithResolver:(EXPromiseResolveBlock)resolve
74
- rejecter:(EXPromiseRejectBlock)reject)
75
- {
76
- _reachabilityRef = [self createReachabilityRef];
77
- SCNetworkReachabilityFlags flags = [self lastFlags];
78
-
79
- if ((flags & kSCNetworkReachabilityFlagsReachable) == 0 ||
80
- (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0) {
81
- _type = EXNetworkTypeNone;
82
- }
83
-
84
- #if !TARGET_OS_TV
85
- else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
86
- _type = EXNetworkTypeCellular;
87
- }
88
- #endif
89
- else {
90
- _type = EXNetworkTypeWifi;
91
- }
92
-
93
- resolve(@{
94
- @"type": [self type],
95
- @"isConnected": @([self connected]),
96
- @"isInternetReachable": @([self connected])
97
- });
98
- }
99
-
100
-
101
- - (SCNetworkReachabilityRef)createReachabilityRef
102
- {
103
- struct sockaddr_in zeroAddress;
104
- bzero(&zeroAddress, sizeof(zeroAddress));
105
- zeroAddress.sin_len = sizeof(zeroAddress);
106
- zeroAddress.sin_family = AF_INET;
107
-
108
- SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *) &zeroAddress);
109
-
110
- // Set the state the first time
111
- SCNetworkReachabilityFlags flags;
112
- SCNetworkReachabilityGetFlags(reachability, &flags);
113
- _lastFlags = flags;
114
-
115
- return reachability;
116
- }
117
-
118
- - (BOOL)connected
119
- {
120
- return ![self.type isEqualToString:EXNetworkTypeUnknown] && ![self.type isEqualToString:EXNetworkTypeNone];
121
- }
122
-
123
- @end
package/unimodule.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "name": "expo-network",
3
- "platforms": ["ios", "android", "web"]
4
- }