@amazon-devices/expo-network 2.0.1758683737

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.
Files changed (51) hide show
  1. package/.eslintrc.js +2 -0
  2. package/CHANGELOG.md +156 -0
  3. package/CMakeLists.txt +50 -0
  4. package/LICENSE +7 -0
  5. package/README.kepler.md +104 -0
  6. package/README.md +44 -0
  7. package/THIRD_PARTY_NOTICES.txt +24 -0
  8. package/android/build.gradle +107 -0
  9. package/android/src/main/AndroidManifest.xml +4 -0
  10. package/android/src/main/java/expo/modules/network/NetworkExceptions.kt +9 -0
  11. package/android/src/main/java/expo/modules/network/NetworkModule.kt +144 -0
  12. package/android/src/main/java/expo/modules/network/NetworkUtils.kt +7 -0
  13. package/build/ExpoNetwork.d.ts +3 -0
  14. package/build/ExpoNetwork.d.ts.map +1 -0
  15. package/build/ExpoNetwork.js +3 -0
  16. package/build/ExpoNetwork.js.map +1 -0
  17. package/build/ExpoNetwork.kepler.d.ts +9 -0
  18. package/build/ExpoNetwork.kepler.d.ts.map +1 -0
  19. package/build/ExpoNetwork.kepler.js +62 -0
  20. package/build/ExpoNetwork.kepler.js.map +1 -0
  21. package/build/ExpoNetwork.web.d.ts +7 -0
  22. package/build/ExpoNetwork.web.d.ts.map +1 -0
  23. package/build/ExpoNetwork.web.js +22 -0
  24. package/build/ExpoNetwork.web.js.map +1 -0
  25. package/build/Network.d.ts +50 -0
  26. package/build/Network.d.ts.map +1 -0
  27. package/build/Network.js +70 -0
  28. package/build/Network.js.map +1 -0
  29. package/build/Network.types.d.ts +62 -0
  30. package/build/Network.types.d.ts.map +1 -0
  31. package/build/Network.types.js +45 -0
  32. package/build/Network.types.js.map +1 -0
  33. package/expo-module.config.json +10 -0
  34. package/ios/Exceptions.swift +7 -0
  35. package/ios/ExpoNetwork.podspec +31 -0
  36. package/ios/NetworkModule.swift +102 -0
  37. package/ios/NetworkType.swift +28 -0
  38. package/kepler/ExpoNetwork.cpp +55 -0
  39. package/kepler/ExpoNetwork.h +24 -0
  40. package/kepler/KeplerInit.cpp +28 -0
  41. package/kepler/NetworkInterfaces.cpp +74 -0
  42. package/kepler/NetworkInterfaces.h +20 -0
  43. package/kepler/test/Network.cpp +147 -0
  44. package/package.json +1 -0
  45. package/react-native.config.js +21 -0
  46. package/src/ExpoNetwork.kepler.ts +80 -0
  47. package/src/ExpoNetwork.ts +2 -0
  48. package/src/ExpoNetwork.web.ts +21 -0
  49. package/src/Network.ts +74 -0
  50. package/src/Network.types.ts +64 -0
  51. package/tsconfig.json +9 -0
@@ -0,0 +1 @@
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"]}
@@ -0,0 +1,9 @@
1
+ import { NetworkState, NetworkStateType } from './Network.types';
2
+ export { NetworkState, NetworkStateType };
3
+ declare const module: {
4
+ getNetworkStateAsync(): Promise<NetworkState>;
5
+ getIpAddressAsync(): Promise<string>;
6
+ isAirplaneModeEnabledAsync(): Promise<boolean>;
7
+ };
8
+ export default module;
9
+ //# sourceMappingURL=ExpoNetwork.kepler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpoNetwork.kepler.d.ts","sourceRoot":"","sources":["../src/ExpoNetwork.kepler.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAE,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EAAC,YAAY,EAAE,gBAAgB,EAAC,CAAC;AAiDxC,QAAA,MAAM,MAAM;4BACsB,OAAO,CAAC,YAAY,CAAC;yBAkBxB,OAAO,CAAC,MAAM,CAAC;kCAGN,OAAO,CAAC,OAAO,CAAC;CAGvD,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { TurboModuleRegistry } from '@amazon-devices/keplerscript-turbomodule-api';
2
+ import { NetworkStateType } from './Network.types';
3
+ export { NetworkStateType };
4
+ const nativeModule = TurboModuleRegistry.getEnforcing('ExpoNetwork');
5
+ const networkStateNumberToType = (num) => {
6
+ switch (num) {
7
+ case 0:
8
+ return NetworkStateType.NONE;
9
+ case 1:
10
+ return NetworkStateType.UNKNOWN;
11
+ case 2:
12
+ return NetworkStateType.CELLULAR;
13
+ case 3:
14
+ return NetworkStateType.WIFI;
15
+ case 4:
16
+ return NetworkStateType.BLUETOOTH;
17
+ case 5:
18
+ return NetworkStateType.ETHERNET;
19
+ case 6:
20
+ return NetworkStateType.WIMAX;
21
+ case 7:
22
+ return NetworkStateType.VPN;
23
+ case 8:
24
+ return NetworkStateType.OTHER;
25
+ default:
26
+ return NetworkStateType.UNKNOWN;
27
+ }
28
+ };
29
+ async function fetchWithTimeout(url) {
30
+ const controller = new AbortController();
31
+ const id = setTimeout(() => controller.abort(), 800);
32
+ const response = await fetch(url, { signal: controller.signal });
33
+ clearTimeout(id);
34
+ return response;
35
+ }
36
+ const module = {
37
+ async getNetworkStateAsync() {
38
+ const state = await nativeModule.getNetworkStateAsync();
39
+ let dnsResponseReceived = false;
40
+ try {
41
+ const response = await fetchWithTimeout('https://dns.google/');
42
+ dnsResponseReceived = !!response?.ok;
43
+ }
44
+ catch (error) {
45
+ dnsResponseReceived = false;
46
+ console.error(error);
47
+ }
48
+ return {
49
+ type: networkStateNumberToType(state.type),
50
+ isConnected: state.isConnected,
51
+ isInternetReachable: dnsResponseReceived,
52
+ };
53
+ },
54
+ async getIpAddressAsync() {
55
+ return nativeModule.getIpAddressAsync();
56
+ },
57
+ async isAirplaneModeEnabledAsync() {
58
+ return nativeModule.isAirplaneModeEnabledAsync();
59
+ },
60
+ };
61
+ export default module;
62
+ //# sourceMappingURL=ExpoNetwork.kepler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpoNetwork.kepler.js","sourceRoot":"","sources":["../src/ExpoNetwork.kepler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,mBAAmB,EAAC,MAAM,oCAAoC,CAAC;AAC1F,OAAO,EAAe,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EAAe,gBAAgB,EAAC,CAAC;AAYxC,MAAM,YAAY,GAAG,mBAAmB,CAAC,YAAY,CAAO,aAAa,CAAS,CAAC;AAEnF,MAAM,wBAAwB,GAAG,CAAC,GAAW,EAAoB,EAAE;IAC/D,QAAQ,GAAG,EAAE,CAAC;QACV,KAAK,CAAC;YACF,OAAO,gBAAgB,CAAC,IAAI,CAAC;QACjC,KAAK,CAAC;YACF,OAAO,gBAAgB,CAAC,OAAO,CAAC;QACpC,KAAK,CAAC;YACF,OAAO,gBAAgB,CAAC,QAAQ,CAAC;QACrC,KAAK,CAAC;YACF,OAAO,gBAAgB,CAAC,IAAI,CAAC;QACjC,KAAK,CAAC;YACF,OAAO,gBAAgB,CAAC,SAAS,CAAC;QACtC,KAAK,CAAC;YACF,OAAO,gBAAgB,CAAC,QAAQ,CAAC;QACrC,KAAK,CAAC;YACF,OAAO,gBAAgB,CAAC,KAAK,CAAC;QAClC,KAAK,CAAC;YACF,OAAO,gBAAgB,CAAC,GAAG,CAAC;QAChC,KAAK,CAAC;YACF,OAAO,gBAAgB,CAAC,KAAK,CAAC;QAClC;YACI,OAAO,gBAAgB,CAAC,OAAO,CAAC;IACxC,CAAC;AACL,CAAC,CAAC;AAEF,KAAK,UAAU,gBAAgB,CAAC,GAAW;IACvC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAC,MAAM,EAAE,UAAU,CAAC,MAAM,EAAC,CAAC,CAAC;IAC/D,YAAY,CAAC,EAAE,CAAC,CAAC;IAEjB,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,MAAM,MAAM,GAAG;IACX,KAAK,CAAC,oBAAoB;QACtB,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,oBAAoB,EAAE,CAAC;QAExD,IAAI,mBAAmB,GAAG,KAAK,CAAC;QAChC,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;YAC/D,mBAAmB,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,mBAAmB,GAAG,KAAK,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QACxB,CAAC;QAED,OAAO;YACH,IAAI,EAAE,wBAAwB,CAAC,KAAK,CAAC,IAAI,CAAC;YAC1C,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,mBAAmB,EAAE,mBAAmB;SAC3C,CAAC;IACN,CAAC;IACD,KAAK,CAAC,iBAAiB;QACnB,OAAO,YAAY,CAAC,iBAAiB,EAAE,CAAC;IAC5C,CAAC;IACD,KAAK,CAAC,0BAA0B;QAC5B,OAAO,YAAY,CAAC,0BAA0B,EAAE,CAAC;IACrD,CAAC;CACJ,CAAC;AAEF,eAAe,MAAM,CAAC","sourcesContent":["import {KeplerTurboModule, TurboModuleRegistry} from '@amazon-devices/keplerscript-turbomodule-api';\nimport {NetworkState, NetworkStateType} from './Network.types';\n\nexport {NetworkState, NetworkStateType};\n\ntype NativeModuleNetworkState = {\n isConnected: boolean; isInternetReachable: boolean; type: number;\n};\n\ninterface Spec extends KeplerTurboModule {\n getNetworkStateAsync(): Promise<NativeModuleNetworkState>;\n getIpAddressAsync(): Promise<string>;\n isAirplaneModeEnabledAsync(): Promise<boolean>;\n}\n\nconst nativeModule = TurboModuleRegistry.getEnforcing<Spec>('ExpoNetwork') as Spec;\n\nconst networkStateNumberToType = (num: number): NetworkStateType => {\n switch (num) {\n case 0:\n return NetworkStateType.NONE;\n case 1:\n return NetworkStateType.UNKNOWN;\n case 2:\n return NetworkStateType.CELLULAR;\n case 3:\n return NetworkStateType.WIFI;\n case 4:\n return NetworkStateType.BLUETOOTH;\n case 5:\n return NetworkStateType.ETHERNET;\n case 6:\n return NetworkStateType.WIMAX;\n case 7:\n return NetworkStateType.VPN;\n case 8:\n return NetworkStateType.OTHER;\n default:\n return NetworkStateType.UNKNOWN;\n }\n};\n\nasync function fetchWithTimeout(url: string) {\n const controller = new AbortController();\n const id = setTimeout(() => controller.abort(), 800);\n\n const response = await fetch(url, {signal: controller.signal});\n clearTimeout(id);\n\n return response;\n}\n\nconst module = {\n async getNetworkStateAsync(): Promise<NetworkState> {\n const state = await nativeModule.getNetworkStateAsync();\n\n let dnsResponseReceived = false;\n try {\n const response = await fetchWithTimeout('https://dns.google/');\n dnsResponseReceived = !!response?.ok;\n } catch (error) {\n dnsResponseReceived = false;\n console.error(error)\n }\n\n return {\n type: networkStateNumberToType(state.type),\n isConnected: state.isConnected,\n isInternetReachable: dnsResponseReceived,\n };\n },\n async getIpAddressAsync(): Promise<string> {\n return nativeModule.getIpAddressAsync();\n },\n async isAirplaneModeEnabledAsync(): Promise<boolean> {\n return nativeModule.isAirplaneModeEnabledAsync();\n },\n};\n\nexport default module;\n"]}
@@ -0,0 +1,7 @@
1
+ import { NetworkState } from './Network.types';
2
+ declare const _default: {
3
+ getIpAddressAsync(): Promise<string>;
4
+ getNetworkStateAsync(): Promise<NetworkState>;
5
+ };
6
+ export default _default;
7
+ //# sourceMappingURL=ExpoNetwork.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpoNetwork.web.d.ts","sourceRoot":"","sources":["../src/ExpoNetwork.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAoB,MAAM,iBAAiB,CAAC;;yBAGpC,OAAO,CAAC,MAAM,CAAC;4BASZ,OAAO,CAAC,YAAY,CAAC;;AAVrD,wBAkBE"}
@@ -0,0 +1,22 @@
1
+ import { NetworkStateType } from './Network.types';
2
+ export default {
3
+ async getIpAddressAsync() {
4
+ try {
5
+ const resp = await fetch('https://api.ipify.org?format=json');
6
+ const data = await resp.json();
7
+ return data.ip;
8
+ }
9
+ catch (e) {
10
+ throw e;
11
+ }
12
+ },
13
+ async getNetworkStateAsync() {
14
+ const isOnline = typeof navigator !== 'undefined' && navigator.onLine;
15
+ return {
16
+ type: isOnline ? NetworkStateType.UNKNOWN : NetworkStateType.NONE,
17
+ isConnected: isOnline,
18
+ isInternetReachable: isOnline,
19
+ };
20
+ },
21
+ };
22
+ //# sourceMappingURL=ExpoNetwork.web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpoNetwork.web.js","sourceRoot":"","sources":["../src/ExpoNetwork.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEjE,eAAe;IACb,KAAK,CAAC,iBAAiB;QACrB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,mCAAmC,CAAC,CAAC;YAC9D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,OAAO,IAAI,CAAC,EAAE,CAAC;QACjB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IACD,KAAK,CAAC,oBAAoB;QACxB,MAAM,QAAQ,GAAG,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,MAAM,CAAC;QACtE,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI;YACjE,WAAW,EAAE,QAAQ;YACrB,mBAAmB,EAAE,QAAQ;SAC9B,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { NetworkState, NetworkStateType } from './Network.types';\n\nexport default {\n async getIpAddressAsync(): Promise<string> {\n try {\n const resp = await fetch('https://api.ipify.org?format=json');\n const data = await resp.json();\n return data.ip;\n } catch (e) {\n throw e;\n }\n },\n async getNetworkStateAsync(): Promise<NetworkState> {\n const isOnline = typeof navigator !== 'undefined' && navigator.onLine;\n return {\n type: isOnline ? NetworkStateType.UNKNOWN : NetworkStateType.NONE,\n isConnected: isOnline,\n isInternetReachable: isOnline,\n };\n },\n};\n"]}
@@ -0,0 +1,50 @@
1
+ import { NetworkState, NetworkStateType } from './Network.types';
2
+ export { NetworkState, NetworkStateType };
3
+ /**
4
+ * Gets the device's current network connection state.
5
+ *
6
+ * On web, `navigator.connection.type` is not available on browsers. So if there is an active
7
+ * network connection, the field `type` returns `NetworkStateType.UNKNOWN`. Otherwise, it returns
8
+ * `NetworkStateType.NONE`.
9
+ * @return A `Promise` that fulfils with a `NetworkState` object.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * await Network.getNetworkStateAsync();
14
+ * // {
15
+ * // type: NetworkStateType.CELLULAR,
16
+ * // isConnected: true,
17
+ * // isInternetReachable: true,
18
+ * // }
19
+ * ```
20
+ */
21
+ export declare function getNetworkStateAsync(): Promise<NetworkState>;
22
+ /**
23
+ * Gets the device's current IPv4 address. Returns `0.0.0.0` if the IP address could not be retrieved.
24
+ *
25
+ * On web, this method uses the third-party [`ipify service`](https://www.ipify.org/) to get the
26
+ * public IP address of the current device.
27
+ * @return A `Promise` that fulfils with a `string` of the current IP address of the device's main
28
+ * network interface. Can only be IPv4 address.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * await Network.getIpAddressAsync();
33
+ * // "92.168.32.44"
34
+ * ```
35
+ */
36
+ export declare function getIpAddressAsync(): Promise<string>;
37
+ /**
38
+ * Tells if the device is in airplane mode.
39
+ * @return Returns a `Promise` that fulfils with a `boolean` value for whether the device is in
40
+ * airplane mode or not.
41
+ * @platform android
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * await Network.isAirplaneModeEnabledAsync();
46
+ * // false
47
+ * ```
48
+ */
49
+ export declare function isAirplaneModeEnabledAsync(): Promise<boolean>;
50
+ //# sourceMappingURL=Network.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Network.d.ts","sourceRoot":"","sources":["../src/Network.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAG1C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,YAAY,CAAC,CAKlE;AAGD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAKzD;AAGD;;;;;;;;;;;GAWG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,OAAO,CAAC,CAKnE"}
@@ -0,0 +1,70 @@
1
+ import { UnavailabilityError } from 'expo-modules-core';
2
+ import ExpoNetwork from './ExpoNetwork';
3
+ import { NetworkStateType } from './Network.types';
4
+ export { NetworkStateType };
5
+ // @needsAudit
6
+ /**
7
+ * Gets the device's current network connection state.
8
+ *
9
+ * On web, `navigator.connection.type` is not available on browsers. So if there is an active
10
+ * network connection, the field `type` returns `NetworkStateType.UNKNOWN`. Otherwise, it returns
11
+ * `NetworkStateType.NONE`.
12
+ * @return A `Promise` that fulfils with a `NetworkState` object.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * await Network.getNetworkStateAsync();
17
+ * // {
18
+ * // type: NetworkStateType.CELLULAR,
19
+ * // isConnected: true,
20
+ * // isInternetReachable: true,
21
+ * // }
22
+ * ```
23
+ */
24
+ export async function getNetworkStateAsync() {
25
+ if (!ExpoNetwork.getNetworkStateAsync) {
26
+ throw new UnavailabilityError('expo-network', 'getNetworkStateAsync');
27
+ }
28
+ return await ExpoNetwork.getNetworkStateAsync();
29
+ }
30
+ // @needsAudit
31
+ /**
32
+ * Gets the device's current IPv4 address. Returns `0.0.0.0` if the IP address could not be retrieved.
33
+ *
34
+ * On web, this method uses the third-party [`ipify service`](https://www.ipify.org/) to get the
35
+ * public IP address of the current device.
36
+ * @return A `Promise` that fulfils with a `string` of the current IP address of the device's main
37
+ * network interface. Can only be IPv4 address.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * await Network.getIpAddressAsync();
42
+ * // "92.168.32.44"
43
+ * ```
44
+ */
45
+ export async function getIpAddressAsync() {
46
+ if (!ExpoNetwork.getIpAddressAsync) {
47
+ throw new UnavailabilityError('expo-network', 'getIpAddressAsync');
48
+ }
49
+ return await ExpoNetwork.getIpAddressAsync();
50
+ }
51
+ // @needsAudit
52
+ /**
53
+ * Tells if the device is in airplane mode.
54
+ * @return Returns a `Promise` that fulfils with a `boolean` value for whether the device is in
55
+ * airplane mode or not.
56
+ * @platform android
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * await Network.isAirplaneModeEnabledAsync();
61
+ * // false
62
+ * ```
63
+ */
64
+ export async function isAirplaneModeEnabledAsync() {
65
+ if (!ExpoNetwork.isAirplaneModeEnabledAsync) {
66
+ throw new UnavailabilityError('expo-network', 'isAirplaneModeEnabledAsync');
67
+ }
68
+ return await ExpoNetwork.isAirplaneModeEnabledAsync();
69
+ }
70
+ //# sourceMappingURL=Network.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Network.js","sourceRoot":"","sources":["../src/Network.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAgB,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEjE,OAAO,EAAgB,gBAAgB,EAAE,CAAC;AAE1C,cAAc;AACd;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,IAAI,CAAC,WAAW,CAAC,oBAAoB,EAAE,CAAC;QACtC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,sBAAsB,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,MAAM,WAAW,CAAC,oBAAoB,EAAE,CAAC;AAClD,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC;QACnC,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,MAAM,WAAW,CAAC,iBAAiB,EAAE,CAAC;AAC/C,CAAC;AAED,cAAc;AACd;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B;IAC9C,IAAI,CAAC,WAAW,CAAC,0BAA0B,EAAE,CAAC;QAC5C,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,4BAA4B,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,MAAM,WAAW,CAAC,0BAA0B,EAAE,CAAC;AACxD,CAAC","sourcesContent":["import { UnavailabilityError } from 'expo-modules-core';\n\nimport ExpoNetwork from './ExpoNetwork';\nimport { NetworkState, NetworkStateType } from './Network.types';\n\nexport { NetworkState, NetworkStateType };\n\n// @needsAudit\n/**\n * Gets the device's current network connection state.\n *\n * On web, `navigator.connection.type` is not available on browsers. So if there is an active\n * network connection, the field `type` returns `NetworkStateType.UNKNOWN`. Otherwise, it returns\n * `NetworkStateType.NONE`.\n * @return A `Promise` that fulfils with a `NetworkState` object.\n *\n * @example\n * ```ts\n * await Network.getNetworkStateAsync();\n * // {\n * // type: NetworkStateType.CELLULAR,\n * // isConnected: true,\n * // isInternetReachable: true,\n * // }\n * ```\n */\nexport async function getNetworkStateAsync(): Promise<NetworkState> {\n if (!ExpoNetwork.getNetworkStateAsync) {\n throw new UnavailabilityError('expo-network', 'getNetworkStateAsync');\n }\n return await ExpoNetwork.getNetworkStateAsync();\n}\n\n// @needsAudit\n/**\n * Gets the device's current IPv4 address. Returns `0.0.0.0` if the IP address could not be retrieved.\n *\n * On web, this method uses the third-party [`ipify service`](https://www.ipify.org/) to get the\n * public IP address of the current device.\n * @return A `Promise` that fulfils with a `string` of the current IP address of the device's main\n * network interface. Can only be IPv4 address.\n *\n * @example\n * ```ts\n * await Network.getIpAddressAsync();\n * // \"92.168.32.44\"\n * ```\n */\nexport async function getIpAddressAsync(): Promise<string> {\n if (!ExpoNetwork.getIpAddressAsync) {\n throw new UnavailabilityError('expo-network', 'getIpAddressAsync');\n }\n return await ExpoNetwork.getIpAddressAsync();\n}\n\n// @needsAudit\n/**\n * Tells if the device is in airplane mode.\n * @return Returns a `Promise` that fulfils with a `boolean` value for whether the device is in\n * airplane mode or not.\n * @platform android\n *\n * @example\n * ```ts\n * await Network.isAirplaneModeEnabledAsync();\n * // false\n * ```\n */\nexport async function isAirplaneModeEnabledAsync(): Promise<boolean> {\n if (!ExpoNetwork.isAirplaneModeEnabledAsync) {\n throw new UnavailabilityError('expo-network', 'isAirplaneModeEnabledAsync');\n }\n return await ExpoNetwork.isAirplaneModeEnabledAsync();\n}\n"]}
@@ -0,0 +1,62 @@
1
+ export type NetworkState = {
2
+ /**
3
+ * A [`NetworkStateType`](#networkstatetype) enum value that represents the current network
4
+ * connection type.
5
+ */
6
+ type?: NetworkStateType;
7
+ /**
8
+ * If there is an active network connection. Note that this does not mean that internet is reachable.
9
+ * This field is `false` if the type is either `Network.NetworkStateType.NONE` or `Network.NetworkStateType.UNKNOWN`,
10
+ * `true` otherwise.
11
+ */
12
+ isConnected?: boolean;
13
+ /**
14
+ * If the internet is reachable with the currently active network connection. On Android, this
15
+ * depends on `NetInfo.isConnected()` (API level < 29) or `ConnectivityManager.getActiveNetwork()`
16
+ * (API level >= 29). On iOS, this value will always be the same as `isConnected`.
17
+ */
18
+ isInternetReachable?: boolean;
19
+ };
20
+ /**
21
+ * An enum of the different types of devices supported by Expo.
22
+ */
23
+ export declare enum NetworkStateType {
24
+ /**
25
+ * No active network connection detected.
26
+ */
27
+ NONE = "NONE",
28
+ /**
29
+ * The connection type could not be determined.
30
+ */
31
+ UNKNOWN = "UNKNOWN",
32
+ /**
33
+ * Active network connection over mobile data or [`DUN-specific`](https://developer.android.com/reference/android/net/ConnectivityManager#TYPE_MOBILE_DUN)
34
+ * mobile connection when setting an upstream connection for tethering.
35
+ */
36
+ CELLULAR = "CELLULAR",
37
+ /**
38
+ * Active network connection over WiFi.
39
+ */
40
+ WIFI = "WIFI",
41
+ /**
42
+ * Active network connection over Bluetooth.
43
+ */
44
+ BLUETOOTH = "BLUETOOTH",
45
+ /**
46
+ * Active network connection over Ethernet.
47
+ */
48
+ ETHERNET = "ETHERNET",
49
+ /**
50
+ * Active network connection over Wimax.
51
+ */
52
+ WIMAX = "WIMAX",
53
+ /**
54
+ * Active network connection over VPN.
55
+ */
56
+ VPN = "VPN",
57
+ /**
58
+ * Active network connection over other network connection types.
59
+ */
60
+ OTHER = "OTHER"
61
+ }
62
+ //# sourceMappingURL=Network.types.d.ts.map
@@ -0,0 +1 @@
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,45 @@
1
+ // @needsAudit
2
+ /**
3
+ * An enum of the different types of devices supported by Expo.
4
+ */
5
+ export var NetworkStateType;
6
+ (function (NetworkStateType) {
7
+ /**
8
+ * No active network connection detected.
9
+ */
10
+ NetworkStateType["NONE"] = "NONE";
11
+ /**
12
+ * The connection type could not be determined.
13
+ */
14
+ NetworkStateType["UNKNOWN"] = "UNKNOWN";
15
+ /**
16
+ * Active network connection over mobile data or [`DUN-specific`](https://developer.android.com/reference/android/net/ConnectivityManager#TYPE_MOBILE_DUN)
17
+ * mobile connection when setting an upstream connection for tethering.
18
+ */
19
+ NetworkStateType["CELLULAR"] = "CELLULAR";
20
+ /**
21
+ * Active network connection over WiFi.
22
+ */
23
+ NetworkStateType["WIFI"] = "WIFI";
24
+ /**
25
+ * Active network connection over Bluetooth.
26
+ */
27
+ NetworkStateType["BLUETOOTH"] = "BLUETOOTH";
28
+ /**
29
+ * Active network connection over Ethernet.
30
+ */
31
+ NetworkStateType["ETHERNET"] = "ETHERNET";
32
+ /**
33
+ * Active network connection over Wimax.
34
+ */
35
+ NetworkStateType["WIMAX"] = "WIMAX";
36
+ /**
37
+ * Active network connection over VPN.
38
+ */
39
+ NetworkStateType["VPN"] = "VPN";
40
+ /**
41
+ * Active network connection over other network connection types.
42
+ */
43
+ NetworkStateType["OTHER"] = "OTHER";
44
+ })(NetworkStateType || (NetworkStateType = {}));
45
+ //# sourceMappingURL=Network.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Network.types.js","sourceRoot":"","sources":["../src/Network.types.ts"],"names":[],"mappings":"AAqBA,cAAc;AACd;;GAEG;AACH,MAAM,CAAN,IAAY,gBAsCX;AAtCD,WAAY,gBAAgB;IAC1B;;OAEG;IACH,iCAAa,CAAA;IACb;;OAEG;IACH,uCAAmB,CAAA;IACnB;;;OAGG;IACH,yCAAqB,CAAA;IACrB;;OAEG;IACH,iCAAa,CAAA;IACb;;OAEG;IACH,2CAAuB,CAAA;IACvB;;OAEG;IACH,yCAAqB,CAAA;IACrB;;OAEG;IACH,mCAAe,CAAA;IACf;;OAEG;IACH,+BAAW,CAAA;IACX;;OAEG;IACH,mCAAe,CAAA;AACjB,CAAC,EAtCW,gBAAgB,KAAhB,gBAAgB,QAsC3B","sourcesContent":["// @needsAudit\nexport type NetworkState = {\n /**\n * A [`NetworkStateType`](#networkstatetype) enum value that represents the current network\n * connection type.\n */\n type?: NetworkStateType;\n /**\n * If there is an active network connection. Note that this does not mean that internet is reachable.\n * This field is `false` if the type is either `Network.NetworkStateType.NONE` or `Network.NetworkStateType.UNKNOWN`,\n * `true` otherwise.\n */\n isConnected?: boolean;\n /**\n * If the internet is reachable with the currently active network connection. On Android, this\n * depends on `NetInfo.isConnected()` (API level < 29) or `ConnectivityManager.getActiveNetwork()`\n * (API level >= 29). On iOS, this value will always be the same as `isConnected`.\n */\n isInternetReachable?: boolean;\n};\n\n// @needsAudit\n/**\n * An enum of the different types of devices supported by Expo.\n */\nexport enum NetworkStateType {\n /**\n * No active network connection detected.\n */\n NONE = 'NONE',\n /**\n * The connection type could not be determined.\n */\n UNKNOWN = 'UNKNOWN',\n /**\n * Active network connection over mobile data or [`DUN-specific`](https://developer.android.com/reference/android/net/ConnectivityManager#TYPE_MOBILE_DUN)\n * mobile connection when setting an upstream connection for tethering.\n */\n CELLULAR = 'CELLULAR',\n /**\n * Active network connection over WiFi.\n */\n WIFI = 'WIFI',\n /**\n * Active network connection over Bluetooth.\n */\n BLUETOOTH = 'BLUETOOTH',\n /**\n * Active network connection over Ethernet.\n */\n ETHERNET = 'ETHERNET',\n /**\n * Active network connection over Wimax.\n */\n WIMAX = 'WIMAX',\n /**\n * Active network connection over VPN.\n */\n VPN = 'VPN',\n /**\n * Active network connection over other network connection types.\n */\n OTHER = 'OTHER',\n}\n"]}
@@ -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
+ }
@@ -0,0 +1,31 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'ExpoNetwork'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.description = package['description']
10
+ s.license = package['license']
11
+ s.author = package['author']
12
+ s.homepage = package['homepage']
13
+ s.platform = :ios, '13.0'
14
+ s.source = { git: 'https://github.com/expo/expo.git' }
15
+ s.static_framework = true
16
+
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
+ }
24
+
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')
26
+ s.source_files = "**/*.h"
27
+ s.vendored_frameworks = "#{s.name}.xcframework"
28
+ else
29
+ s.source_files = "**/*.{h,m,swift}"
30
+ end
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
+ }
@@ -0,0 +1,55 @@
1
+ /*
2
+ * Copyright (c) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL
5
+ *
6
+ * Use is subject to license terms.
7
+ */
8
+
9
+ #include "ExpoNetwork.h"
10
+
11
+ #include <KeplerScript/logger/KPLog.h>
12
+
13
+ #include "NetworkInterfaces.h"
14
+
15
+ ExpoNetwork::ExpoNetwork() : volta::react::KeplerTurboModule("ExpoNetwork") {
16
+ volta::react::KPLog.debug("ExpoNetwork constructor {}", name());
17
+ }
18
+
19
+ volta::react::Promise ExpoNetwork::getIpAddressAsync() {
20
+ return volta::react::Promise([](std::shared_ptr<volta::react::Promise> promise) {
21
+ auto interfaces = NetworkInterfaces();
22
+ promise->resolve(interfaces.wlanInterfaceAddress());
23
+ });
24
+ }
25
+
26
+ volta::react::Promise ExpoNetwork::getNetworkStateAsync() {
27
+ return volta::react::Promise([](std::shared_ptr<volta::react::Promise> promise) {
28
+ try {
29
+ auto interfaces = NetworkInterfaces();
30
+ bool isConnected = interfaces.isNetworkConnected();
31
+
32
+ auto networkState = utils::json::JsonContainer::createJsonObject();
33
+ networkState.insert("isConnected", isConnected);
34
+ networkState.insert("type", isConnected ? 3 : 0);
35
+
36
+ promise->resolve(networkState);
37
+ } catch (std::exception& e) {
38
+ volta::react::KPLog.debug("Can't get network state: {}", std::string(e.what()));
39
+ promise->reject(std::string{"Can't get network state: " + std::string(e.what())});
40
+ }
41
+ });
42
+ }
43
+
44
+ volta::react::Promise ExpoNetwork::isAirplaneModeEnabledAsync() {
45
+ return volta::react::Promise([](std::shared_ptr<volta::react::Promise> promise) { promise->resolve(false); });
46
+ }
47
+
48
+ void ExpoNetwork::aggregateMethods(
49
+ volta::react::MethodAggregator<volta::react::KeplerTurboModule>& methodAggregator) const noexcept {
50
+ volta::react::KPLog.debug("methodAggregator");
51
+
52
+ methodAggregator.addMethod("getNetworkStateAsync", 0, &ExpoNetwork::getNetworkStateAsync);
53
+ methodAggregator.addMethod("getIpAddressAsync", 0, &ExpoNetwork::getIpAddressAsync);
54
+ methodAggregator.addMethod("isAirplaneModeEnabledAsync", 0, &ExpoNetwork::isAirplaneModeEnabledAsync);
55
+ }
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Copyright (c) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * PROPRIETARY/CONFIDENTIAL
5
+ *
6
+ * Use is subject to license terms.
7
+ */
8
+
9
+ #include <KeplerScript/modules/KeplerTurboModule.h>
10
+
11
+ class KEPLERSCRIPT_EXPORT ExpoNetwork : public volta::react::KeplerTurboModule {
12
+ public:
13
+ ExpoNetwork();
14
+
15
+ #ifndef UNIT_TEST
16
+ protected:
17
+ #endif
18
+ volta::react::Promise getIpAddressAsync();
19
+ volta::react::Promise getNetworkStateAsync();
20
+ volta::react::Promise isAirplaneModeEnabledAsync();
21
+
22
+ void aggregateMethods(
23
+ volta::react::MethodAggregator<volta::react::KeplerTurboModule>& methodAggregator) const noexcept override;
24
+ };