expo-device 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.
@@ -0,0 +1,261 @@
1
+ import UIKit
2
+
3
+ struct ExpoDeviceType {
4
+ let modelName: String
5
+ let deviceYearClass: Int?
6
+ }
7
+
8
+ public extension UIDevice {
9
+ // Credit: https://stackoverflow.com/a/26962452
10
+ static let modelIdentifier: String = {
11
+ var systemInfo = utsname()
12
+ uname(&systemInfo)
13
+ let machineMirror = Mirror(reflecting: systemInfo.machine)
14
+ let identifier = machineMirror.children.reduce("") { identifier, element in
15
+ guard let value = element.value as? Int8, value != 0 else {
16
+ return identifier
17
+ }
18
+ return identifier + String(UnicodeScalar(UInt8(value)))
19
+ }
20
+
21
+ return identifier
22
+ }()
23
+
24
+ // swiftlint:disable function_body_length closure_body_length
25
+ static internal let DeviceMap: ExpoDeviceType = {
26
+ func mapToDevice(identifier: String) -> ExpoDeviceType {
27
+ let currentYear = Calendar(identifier: .gregorian).dateComponents([.year], from: Date()).year
28
+
29
+ #if os(iOS)
30
+ switch identifier {
31
+ case "iPod7,1":
32
+ return ExpoDeviceType(modelName: "iPod touch (6th generation)", deviceYearClass: 2015)
33
+ case "iPod9,1":
34
+ return ExpoDeviceType(modelName: "iPod touch (7th generation)", deviceYearClass: 2019)
35
+ case "iPhone6,1", "iPhone6,2":
36
+ return ExpoDeviceType(modelName: "iPhone 5s", deviceYearClass: 2013)
37
+ case "iPhone7,1":
38
+ return ExpoDeviceType(modelName: "iPhone 6 Plus", deviceYearClass: 2014)
39
+ case "iPhone7,2":
40
+ return ExpoDeviceType(modelName: "iPhone 6", deviceYearClass: 2014)
41
+ case "iPhone8,1":
42
+ return ExpoDeviceType(modelName: "iPhone 6s", deviceYearClass: 2015)
43
+ case "iPhone8,2":
44
+ return ExpoDeviceType(modelName: "iPhone 6s Plus", deviceYearClass: 2015)
45
+ case "iPhone9,1", "iPhone9,3":
46
+ return ExpoDeviceType(modelName: "iPhone 7", deviceYearClass: 2016)
47
+ case "iPhone9,2", "iPhone9,4":
48
+ return ExpoDeviceType(modelName: "iPhone 7 Plus", deviceYearClass: 2016)
49
+ case "iPhone10,1", "iPhone10,4":
50
+ return ExpoDeviceType(modelName: "iPhone 8", deviceYearClass: 2017)
51
+ case "iPhone10,2", "iPhone10,5":
52
+ return ExpoDeviceType(modelName: "iPhone 8 Plus", deviceYearClass: 2017)
53
+ case "iPhone10,3", "iPhone10,6":
54
+ return ExpoDeviceType(modelName: "iPhone X", deviceYearClass: 2017)
55
+ case "iPhone11,2":
56
+ return ExpoDeviceType(modelName: "iPhone XS", deviceYearClass: 2018)
57
+ case "iPhone11,4", "iPhone11,6":
58
+ return ExpoDeviceType(modelName: "iPhone XS Max", deviceYearClass: 2018)
59
+ case "iPhone11,8":
60
+ return ExpoDeviceType(modelName: "iPhone XR", deviceYearClass: 2018)
61
+ case "iPhone12,1":
62
+ return ExpoDeviceType(modelName: "iPhone 11", deviceYearClass: 2019)
63
+ case "iPhone12,3":
64
+ return ExpoDeviceType(modelName: "iPhone 11 Pro", deviceYearClass: 2019)
65
+ case "iPhone12,5":
66
+ return ExpoDeviceType(modelName: "iPhone 11 Pro Max", deviceYearClass: 2019)
67
+ case "iPhone13,1":
68
+ return ExpoDeviceType(modelName: "iPhone 12 mini", deviceYearClass: 2020)
69
+ case "iPhone13,2":
70
+ return ExpoDeviceType(modelName: "iPhone 12", deviceYearClass: 2020)
71
+ case "iPhone13,3":
72
+ return ExpoDeviceType(modelName: "iPhone 12 Pro", deviceYearClass: 2020)
73
+ case "iPhone13,4":
74
+ return ExpoDeviceType(modelName: "iPhone 12 Pro Max", deviceYearClass: 2020)
75
+ case "iPhone14,4":
76
+ return ExpoDeviceType(modelName: "iPhone 13 mini", deviceYearClass: 2021)
77
+ case "iPhone14,5":
78
+ return ExpoDeviceType(modelName: "iPhone 13", deviceYearClass: 2021)
79
+ case "iPhone14,2":
80
+ return ExpoDeviceType(modelName: "iPhone 13 Pro", deviceYearClass: 2021)
81
+ case "iPhone14,3":
82
+ return ExpoDeviceType(modelName: "iPhone 13 Pro Max", deviceYearClass: 2021)
83
+ case "iPhone14,7":
84
+ return ExpoDeviceType(modelName: "iPhone 14", deviceYearClass: 2022)
85
+ case "iPhone14,8":
86
+ return ExpoDeviceType(modelName: "iPhone 14 Plus", deviceYearClass: 2022)
87
+ case "iPhone15,2":
88
+ return ExpoDeviceType(modelName: "iPhone 14 Pro", deviceYearClass: 2022)
89
+ case "iPhone15,3":
90
+ return ExpoDeviceType(modelName: "iPhone 14 Pro Max", deviceYearClass: 2022)
91
+ case "iPhone8,4":
92
+ return ExpoDeviceType(modelName: "iPhone SE", deviceYearClass: 2016)
93
+ case "iPhone12,8":
94
+ return ExpoDeviceType(modelName: "iPhone SE (2nd generation)", deviceYearClass: 2020)
95
+ case "iPhone14,6":
96
+ return ExpoDeviceType(modelName: "iPhone SE (3rd generation)", deviceYearClass: 2022)
97
+ case "iPad6,11", "iPad6,12":
98
+ return ExpoDeviceType(modelName: "iPad (5th generation)", deviceYearClass: 2017)
99
+ case "iPad7,5", "iPad7,6":
100
+ return ExpoDeviceType(modelName: "iPad (6th generation)", deviceYearClass: 2018)
101
+ case "iPad7,11", "iPad7,12":
102
+ return ExpoDeviceType(modelName: "iPad (7th generation)", deviceYearClass: 2019)
103
+ case "iPad11,6", "iPad11,7":
104
+ return ExpoDeviceType(modelName: "iPad (8th generation)", deviceYearClass: 2020)
105
+ case "iPad12,1", "iPad12,2":
106
+ return ExpoDeviceType(modelName: "iPad (9th generation)", deviceYearClass: 2021)
107
+ case "iPad4,1", "iPad4,2", "iPad4,3":
108
+ return ExpoDeviceType(modelName: "iPad Air", deviceYearClass: 2013)
109
+ case "iPad5,3", "iPad5,4":
110
+ return ExpoDeviceType(modelName: "iPad Air 2", deviceYearClass: 2014)
111
+ case "iPad11,3", "iPad11,4":
112
+ return ExpoDeviceType(modelName: "iPad Air (3rd generation)", deviceYearClass: 2019)
113
+ case "iPad13,1", "iPad13,2":
114
+ return ExpoDeviceType(modelName: "iPad Air (4th generation)", deviceYearClass: 2020)
115
+ case "iPad13,16", "iPad13,17":
116
+ return ExpoDeviceType(modelName: "iPad Air (5th generation)", deviceYearClass: 2022)
117
+ case "iPad4,4", "iPad4,5", "iPad4,6":
118
+ return ExpoDeviceType(modelName: "iPad mini 2", deviceYearClass: 2013)
119
+ case "iPad4,7", "iPad4,8", "iPad4,9":
120
+ return ExpoDeviceType(modelName: "iPad mini 3", deviceYearClass: 2014)
121
+ case "iPad5,1", "iPad5,2":
122
+ return ExpoDeviceType(modelName: "iPad mini 4", deviceYearClass: 2015)
123
+ case "iPad11,1", "iPad11,2":
124
+ return ExpoDeviceType(modelName: "iPad mini (5th generation)", deviceYearClass: 2019)
125
+ case "iPad14,1", "iPad14,2":
126
+ return ExpoDeviceType(modelName: "iPad mini (6th generation)", deviceYearClass: 2021)
127
+ case "iPad6,3", "iPad6,4":
128
+ return ExpoDeviceType(modelName: "iPad Pro (9.7-inch)", deviceYearClass: 2016)
129
+ case "iPad7,3", "iPad7,4":
130
+ return ExpoDeviceType(modelName: "iPad Pro (10.5-inch)", deviceYearClass: 2017)
131
+ case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4":
132
+ return ExpoDeviceType(modelName: "iPad Pro (11-inch) (1st generation)", deviceYearClass: 2018)
133
+ case "iPad8,9", "iPad8,10":
134
+ return ExpoDeviceType(modelName: "iPad Pro (11-inch) (2nd generation)", deviceYearClass: 2020)
135
+ case "iPad13,4", "iPad13,5", "iPad13,6", "iPad13,7":
136
+ return ExpoDeviceType(modelName: "iPad Pro (11-inch) (3rd generation)", deviceYearClass: 2021)
137
+ case "iPad6,7", "iPad6,8":
138
+ return ExpoDeviceType(modelName: "iPad Pro (12.9-inch) (1st generation)", deviceYearClass: 2015)
139
+ case "iPad7,1", "iPad7,2":
140
+ return ExpoDeviceType(modelName: "iPad Pro (12.9-inch) (2nd generation)", deviceYearClass: 2017)
141
+ case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8":
142
+ return ExpoDeviceType(modelName: "iPad Pro (12.9-inch) (3rd generation)", deviceYearClass: 2018)
143
+ case "iPad8,11", "iPad8,12":
144
+ return ExpoDeviceType(modelName: "iPad Pro (12.9-inch) (4th generation)", deviceYearClass: 2020)
145
+ case "iPad13,8", "iPad13,9", "iPad13,10", "iPad13,11":
146
+ return ExpoDeviceType(modelName: "iPad Pro (12.9-inch) (5th generation)", deviceYearClass: 2021)
147
+ case "AppleTV5,3":
148
+ return ExpoDeviceType(modelName: "Apple TV HD (4th Generation, Siri)", deviceYearClass: 2015)
149
+ case "AppleTV6,2":
150
+ return ExpoDeviceType(modelName: "Apple TV 4K", deviceYearClass: 2017)
151
+ case "i386", "x86_64", "arm64":
152
+ return ExpoDeviceType(modelName: "Simulator iOS", deviceYearClass: currentYear)
153
+ default:
154
+ return ExpoDeviceType(modelName: identifier, deviceYearClass: currentYear)
155
+ }
156
+ #elseif os(tvOS)
157
+ switch identifier {
158
+ case "AppleTV5,3":
159
+ return ExpoDeviceType(modelName: "Apple TV HD (4th Generation, Siri)", deviceYearClass: 2015)
160
+ case "AppleTV6,2":
161
+ return ExpoDeviceType(modelName: "Apple TV 4K", deviceYearClass: 2017)
162
+ case "i386", "x86_64":
163
+ return ExpoDeviceType(modelName: "Simulator tvOS", deviceYearClass: currentYear)
164
+ default:
165
+ return identifier
166
+ }
167
+ #endif
168
+ }
169
+
170
+ return mapToDevice(identifier: modelIdentifier)
171
+ }()
172
+ // swiftlint:enable function_body_length closure_body_length
173
+
174
+ // Credit: https://github.com/developerinsider/isJailBroken/blob/master/IsJailBroken/Extension/UIDevice%2BJailBroken.swift
175
+ var isSimulator: Bool {
176
+ return TARGET_OS_SIMULATOR != 0
177
+ }
178
+
179
+ var isJailbroken: Bool {
180
+ if UIDevice.current.isSimulator {
181
+ return false
182
+ }
183
+
184
+ let jailbroken = JailbreakHelper.hasCydiaInstalled() || JailbreakHelper.doesContainSuspiciousApps() ||
185
+ JailbreakHelper.doesSuspiciousSystemPathExist() || JailbreakHelper.canEditSystemFiles()
186
+
187
+ return jailbroken
188
+ }
189
+ }
190
+
191
+ // Credit: https://github.com/developerinsider/isJailBroken/blob/master/IsJailBroken/Extension/UIDevice%2BJailBroken.swift
192
+ private struct JailbreakHelper {
193
+ static func hasCydiaInstalled() -> Bool {
194
+ if let url = URL(string: "cydia://") {
195
+ return UIApplication.shared.canOpenURL(url)
196
+ }
197
+ return false
198
+ }
199
+
200
+ static func doesContainSuspiciousApps() -> Bool {
201
+ for path in suspiciousAppsPathToCheck where FileManager.default.fileExists(atPath: path) {
202
+ return true
203
+ }
204
+ return false
205
+ }
206
+
207
+ static func doesSuspiciousSystemPathExist() -> Bool {
208
+ for path in suspiciousSystemPathsToCheck where FileManager.default.fileExists(atPath: path) {
209
+ return true
210
+ }
211
+ return false
212
+ }
213
+
214
+ static func canEditSystemFiles() -> Bool {
215
+ let jailbreakText = "Developer Insider"
216
+ do {
217
+ try jailbreakText.write(toFile: jailbreakText, atomically: true, encoding: .utf8)
218
+ return true
219
+ } catch {
220
+ return false
221
+ }
222
+ }
223
+
224
+ /**
225
+ Add more paths here to check for jail break
226
+ */
227
+ static var suspiciousAppsPathToCheck: [String] {
228
+ return [
229
+ "/Applications/Cydia.app",
230
+ "/Applications/blackra1n.app",
231
+ "/Applications/FakeCarrier.app",
232
+ "/Applications/Icy.app",
233
+ "/Applications/IntelliScreen.app",
234
+ "/Applications/MxTube.app",
235
+ "/Applications/RockApp.app",
236
+ "/Applications/SBSettings.app",
237
+ "/Applications/WinterBoard.app"
238
+ ]
239
+ }
240
+
241
+ static var suspiciousSystemPathsToCheck: [String] {
242
+ return [
243
+ "/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist",
244
+ "/Library/MobileSubstrate/DynamicLibraries/Veency.plist",
245
+ "/private/var/lib/apt",
246
+ "/private/var/lib/apt/",
247
+ "/private/var/lib/cydia",
248
+ "/private/var/mobile/Library/SBSettings/Themes",
249
+ "/private/var/stash",
250
+ "/private/var/tmp/cydia.log",
251
+ "/System/Library/LaunchDaemons/com.ikey.bbot.plist",
252
+ "/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist",
253
+ "/usr/bin/sshd",
254
+ "/usr/libexec/sftp-server",
255
+ "/usr/sbin/sshd",
256
+ "/etc/apt",
257
+ "/bin/bash",
258
+ "/Library/MobileSubstrate/MobileSubstrate.dylib"
259
+ ]
260
+ }
261
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-device",
3
- "version": "5.0.0",
3
+ "version": "5.2.0",
4
4
  "description": "A universal module that gets physical information about the device running the application",
5
5
  "main": "build/Device.js",
6
6
  "types": "build/Device.d.ts",
@@ -33,7 +33,7 @@
33
33
  "license": "MIT",
34
34
  "homepage": "https://docs.expo.dev/versions/latest/sdk/device/",
35
35
  "dependencies": {
36
- "ua-parser-js": "^0.7.19"
36
+ "ua-parser-js": "^0.7.33"
37
37
  },
38
38
  "devDependencies": {
39
39
  "expo-module-scripts": "^3.0.0"
@@ -41,5 +41,5 @@
41
41
  "peerDependencies": {
42
42
  "expo": "*"
43
43
  },
44
- "gitHead": "eab2b09c735fb0fc2bf734a3f29a6593adba3838"
44
+ "gitHead": "1815e2eaad8c753588c7b1eb74420174a28e01f4"
45
45
  }
package/src/Device.ts CHANGED
@@ -5,30 +5,216 @@ import ExpoDevice from './ExpoDevice';
5
5
 
6
6
  export { DeviceType };
7
7
 
8
+ /**
9
+ * `true` if the app is running on a real device and `false` if running in a simulator or emulator.
10
+ * On web, this is always set to `true`.
11
+ */
8
12
  export const isDevice: boolean = ExpoDevice ? ExpoDevice.isDevice : true;
13
+
14
+ /**
15
+ * The device brand. The consumer-visible brand of the product/hardware. On web, this value is always `null`.
16
+ *
17
+ * @example
18
+ * ```js
19
+ * Device.brand; // Android: "google", "xiaomi"; iOS: "Apple"; web: null
20
+ * ```
21
+ * @platform android
22
+ * @platform ios
23
+ */
9
24
  export const brand: string | null = ExpoDevice ? ExpoDevice.brand : null;
25
+
26
+ /**
27
+ * The actual device manufacturer of the product or hardware. This value of this field may be `null` if it cannot be determined.
28
+ *
29
+ * To view difference between `brand` and `manufacturer` on Android see [official documentation](https://developer.android.com/reference/android/os/Build).
30
+ *
31
+ * @example
32
+ * ```js
33
+ * Device.manufacturer; // Android: "Google", "xiaomi"; iOS: "Apple"; web: "Google", null
34
+ * ```
35
+ */
10
36
  export const manufacturer: string | null = ExpoDevice ? ExpoDevice.manufacturer : null;
37
+
38
+ /**
39
+ * The internal model ID of the device. This is useful for programmatically identifying the type of device and is not a human-friendly string.
40
+ * On web and Android, this value is always `null`.
41
+ *
42
+ * @example
43
+ * ```js
44
+ * Device.modelId; // iOS: "iPhone7,2"; Android: null; web: null
45
+ * ```
46
+ * @platform ios
47
+ */
11
48
  export const modelId = ExpoDevice ? ExpoDevice.modelId || null : null;
49
+
50
+ /**
51
+ * The human-friendly name of the device model. This is the name that people would typically use to refer to the device rather than a programmatic model identifier.
52
+ * This value of this field may be `null` if it cannot be determined.
53
+ *
54
+ * @example
55
+ * ```js
56
+ * Device.modelName; // Android: "Pixel 2"; iOS: "iPhone XS Max"; web: "iPhone", null
57
+ * ```
58
+ */
12
59
  export const modelName: string | null = ExpoDevice ? ExpoDevice.modelName : null;
60
+
61
+ /**
62
+ * The specific configuration or name of the industrial design. It represents the device's name when it was designed during manufacturing into mass production.
63
+ * On Android, it corresponds to [`Build.DEVICE`](https://developer.android.com/reference/android/os/Build#DEVICE). On web and iOS, this value is always `null`.
64
+ *
65
+ * @example
66
+ * ```js
67
+ * Device.designName; // Android: "kminilte"; iOS: null; web: null
68
+ * ```
69
+ * @platform android
70
+ */
13
71
  export const designName: string | null = ExpoDevice ? ExpoDevice.designName || null : null;
72
+
73
+ /**
74
+ * The device's overall product name chosen by the device implementer containing the development name or code name of the device.
75
+ * Corresponds to [`Build.PRODUCT`](https://developer.android.com/reference/android/os/Build#PRODUCT). On web and iOS, this value is always `null`.
76
+ *
77
+ * @example
78
+ * ```js
79
+ * Device.productName; // Android: "kminiltexx"; iOS: null; web: null
80
+ * ```
81
+ * @platform android
82
+ */
14
83
  export const productName: string | null = ExpoDevice ? ExpoDevice.productName || null : null;
84
+
85
+ /**
86
+ * The [device year class](https://github.com/facebook/device-year-class) of this device. On web, this value is always `null`.
87
+ */
15
88
  export const deviceYearClass: number | null = ExpoDevice ? ExpoDevice.deviceYearClass : null;
89
+
90
+ /**
91
+ * The device's total memory, in bytes. This is the total memory accessible to the kernel, but not necessarily to a single app.
92
+ * This is basically the amount of RAM the device has, not including below-kernel fixed allocations like DMA buffers, RAM for the baseband CPU, etc…
93
+ * On web, this value is always `null`.
94
+ *
95
+ * @example
96
+ * ```js
97
+ * Device.totalMemory; // 17179869184
98
+ * ```
99
+ */
16
100
  export const totalMemory: number | null = ExpoDevice ? ExpoDevice.totalMemory : null;
101
+
102
+ /**
103
+ * A list of supported processor architecture versions. The device expects the binaries it runs to be compiled for one of these architectures.
104
+ * This value is `null` if the supported architectures could not be determined, particularly on web.
105
+ *
106
+ * @example
107
+ * ```js
108
+ * Device.supportedCpuArchitectures; // ['arm64 v8', 'Intel x86-64h Haswell', 'arm64-v8a', 'armeabi-v7a", 'armeabi']
109
+ * ```
110
+ */
17
111
  export const supportedCpuArchitectures: string[] | null = ExpoDevice
18
112
  ? ExpoDevice.supportedCpuArchitectures
19
113
  : null;
114
+
115
+ /**
116
+ * The name of the OS running on the device.
117
+ *
118
+ * @example
119
+ * ```js
120
+ * Device.osName; // Android: "Android"; iOS: "iOS" or "iPadOS"; web: "iOS", "Android", "Windows"
121
+ * ```
122
+ */
20
123
  export const osName: string | null = ExpoDevice ? ExpoDevice.osName : null;
124
+
125
+ /**
126
+ * The human-readable OS version string. Note that the version string may not always contain three numbers separated by dots.
127
+ *
128
+ * @example
129
+ * ```js
130
+ * Device.osVersion; // Android: "4.0.3"; iOS: "12.3.1"; web: "11.0", "8.1.0"
131
+ * ```
132
+ */
21
133
  export const osVersion: string | null = ExpoDevice ? ExpoDevice.osVersion : null;
134
+
135
+ /**
136
+ * The build ID of the OS that more precisely identifies the version of the OS. On Android, this corresponds to `Build.DISPLAY` (not `Build.ID`)
137
+ * and currently is a string as described [here](https://source.android.com/setup/start/build-numbers). On iOS, this corresponds to `kern.osversion`
138
+ * and is the detailed OS version sometimes displayed next to the more human-readable version. On web, this value is always `null`.
139
+ *
140
+ * @example
141
+ * ```js
142
+ * Device.osBuildId; // Android: "PSR1.180720.075"; iOS: "16F203"; web: null
143
+ * ```
144
+ */
22
145
  export const osBuildId: string | null = ExpoDevice ? ExpoDevice.osBuildId : null;
146
+
147
+ /**
148
+ * The internal build ID of the OS running on the device. On Android, this corresponds to `Build.ID`.
149
+ * On iOS, this is the same value as [`Device.osBuildId`](#deviceosbuildid). On web, this value is always `null`.
150
+ *
151
+ * @example
152
+ * ```js
153
+ * Device.osInternalBuildId; // Android: "MMB29K"; iOS: "16F203"; web: null,
154
+ * ```
155
+ */
23
156
  export const osInternalBuildId: string | null = ExpoDevice ? ExpoDevice.osInternalBuildId : null;
157
+
158
+ /**
159
+ * A string that uniquely identifies the build of the currently running system OS. On Android, it follows this template:
160
+ * - `$(BRAND)/$(PRODUCT)/$(DEVICE)/$(BOARD):$(VERSION.RELEASE)/$(ID)/$(VERSION.INCREMENTAL):$(TYPE)/\$(TAGS)`
161
+ * On web and iOS, this value is always `null`.
162
+ *
163
+ * @example
164
+ * ```js
165
+ * Device.osBuildFingerprint;
166
+ * // Android: "google/sdk_gphone_x86/generic_x86:9/PSR1.180720.075/5124027:user/release-keys";
167
+ * // iOS: null; web: null
168
+ * ```
169
+ * @platform android
170
+ */
24
171
  export const osBuildFingerprint: string | null = ExpoDevice
25
172
  ? ExpoDevice.osBuildFingerprint || null
26
173
  : null;
174
+
175
+ /**
176
+ * The Android SDK version of the software currently running on this hardware device. This value never changes while a device is booted,
177
+ * but it may increase when the hardware manufacturer provides an OS update. See [here](https://developer.android.com/reference/android/os/Build.VERSION_CODES.html)
178
+ * to see all possible version codes and corresponding versions. On iOS and web, this value is always `null`.
179
+ *
180
+ * @example
181
+ * ```js
182
+ * Device.platformApiLevel; // Android: 19; iOS: null; web: null
183
+ * ```
184
+ * @platform android
185
+ */
27
186
  export const platformApiLevel: number | null = ExpoDevice
28
187
  ? ExpoDevice.platformApiLevel || null
29
188
  : null;
189
+
190
+ /**
191
+ * The human-readable name of the device, which may be set by the device's user. If the device name is unavailable, particularly on web, this value is `null`.
192
+ *
193
+ * > On iOS 16 and newer, this value will be set to generic "iPhone" until you add the correct entitlement, see [iOS Capabilities page](/build-reference/ios-capabilities)
194
+ * > to learn how to add one and check out [Apple documentation](https://developer.apple.com/documentation/uikit/uidevice/1620015-name#discussion)
195
+ * > for more details on this change.
196
+ *
197
+ * @example
198
+ * ```js
199
+ * Device.deviceName; // "Vivian's iPhone XS"
200
+ * ```
201
+ */
30
202
  export const deviceName: string | null = ExpoDevice ? ExpoDevice.deviceName : null;
31
203
 
204
+ /**
205
+ * Checks the type of the device as a [`DeviceType`](#devicetype) enum value.
206
+ *
207
+ * On Android, for devices other than TVs, the device type is determined by the screen resolution (screen diagonal size), so the result may not be completely accurate.
208
+ * If the screen diagonal length is between 3" and 6.9", the method returns `DeviceType.PHONE`. For lengths between 7" and 18", the method returns `DeviceType.TABLET`.
209
+ * Otherwise, the method returns `DeviceType.UNKNOWN`.
210
+ *
211
+ * @return Returns a promise that resolves to a [`DeviceType`](#devicetype) enum value.
212
+ * @example
213
+ * ```js
214
+ * await Device.getDeviceTypeAsync();
215
+ * // DeviceType.PHONE
216
+ * ```
217
+ */
32
218
  export async function getDeviceTypeAsync(): Promise<DeviceType> {
33
219
  if (!ExpoDevice.getDeviceTypeAsync) {
34
220
  throw new UnavailabilityError('expo-device', 'getDeviceTypeAsync');
@@ -36,6 +222,17 @@ export async function getDeviceTypeAsync(): Promise<DeviceType> {
36
222
  return await ExpoDevice.getDeviceTypeAsync();
37
223
  }
38
224
 
225
+ /**
226
+ * Gets the uptime since the last reboot of the device, in milliseconds. Android devices do not count time spent in deep sleep.
227
+ * @return Returns a promise that resolves to a `number` that represents the milliseconds since last reboot.
228
+ * @example
229
+ * ```js
230
+ * await Device.getUptimeAsync();
231
+ * // 4371054
232
+ * ```
233
+ * @platform android
234
+ * @platform ios
235
+ */
39
236
  export async function getUptimeAsync(): Promise<number> {
40
237
  if (!ExpoDevice.getUptimeAsync) {
41
238
  throw new UnavailabilityError('expo-device', 'getUptimeAsync');
@@ -43,6 +240,16 @@ export async function getUptimeAsync(): Promise<number> {
43
240
  return await ExpoDevice.getUptimeAsync();
44
241
  }
45
242
 
243
+ /**
244
+ * Returns the maximum amount of memory that the Java VM will attempt to use. If there is no inherent limit then `Number.MAX_SAFE_INTEGER` is returned.
245
+ * @return Returns a promise that resolves to the maximum available memory that the Java VM will use, in bytes.
246
+ * @example
247
+ * ```js
248
+ * await Device.getMaxMemoryAsync();
249
+ * // 402653184
250
+ * ```
251
+ * @platform android
252
+ */
46
253
  export async function getMaxMemoryAsync(): Promise<number> {
47
254
  if (!ExpoDevice.getMaxMemoryAsync) {
48
255
  throw new UnavailabilityError('expo-device', 'getMaxMemoryAsync');
@@ -54,6 +261,22 @@ export async function getMaxMemoryAsync(): Promise<number> {
54
261
  return maxMemory;
55
262
  }
56
263
 
264
+ /**
265
+ * > **warning** This method is experimental and is not completely reliable. See description below.
266
+ *
267
+ * Checks whether the device has been rooted (Android) or jailbroken (iOS). This is not completely reliable because there exist solutions to bypass root-detection
268
+ * on both [iOS](https://www.theiphonewiki.com/wiki/XCon) and [Android](https://tweakerlinks.com/how-to-bypass-apps-root-detection-in-android-device/).
269
+ * Further, many root-detection checks can be bypassed via reverse engineering.
270
+ * - On Android, it's implemented in a way to find all possible files paths that contain the `"su"` executable but some devices that are not rooted may also have this executable. Therefore, there's no guarantee that this method will always return correctly.
271
+ * - On iOS, [these jailbreak checks](https://www.theiphonewiki.com/wiki/Bypassing_Jailbreak_Detection) are used to detect if a device is rooted/jailbroken. However, since there are closed-sourced solutions such as [xCon](https://www.theiphonewiki.com/wiki/XCon) that aim to hook every known method and function responsible for informing an application of a jailbroken device, this method may not reliably detect devices that have xCon or similar packages installed.
272
+ * - On web, this always resolves to `false` even if the device is rooted.
273
+ * @return Returns a promise that resolves to a `boolean` that specifies whether this device is rooted.
274
+ * @example
275
+ * ```js
276
+ * await Device.isRootedExperimentalAsync();
277
+ * // true or false
278
+ * ```
279
+ */
57
280
  export async function isRootedExperimentalAsync(): Promise<boolean> {
58
281
  if (!ExpoDevice.isRootedExperimentalAsync) {
59
282
  throw new UnavailabilityError('expo-device', 'isRootedExperimentalAsync');
@@ -61,6 +284,18 @@ export async function isRootedExperimentalAsync(): Promise<boolean> {
61
284
  return await ExpoDevice.isRootedExperimentalAsync();
62
285
  }
63
286
 
287
+ /**
288
+ * **Using this method requires you to [add the `REQUEST_INSTALL_PACKAGES` permission](/config/app#permissions).**
289
+ * Returns whether applications can be installed for this user via the system's [Intent#ACTION_INSTALL_PACKAGE](https://developer.android.com/reference/android/content/Intent.html#ACTION_INSTALL_PACKAGE)
290
+ * mechanism rather than through the OS's default app store, like Google Play.
291
+ * @return Returns a promise that resolves to a `boolean` that represents whether the calling package is allowed to request package installation.
292
+ * @example
293
+ * ```js
294
+ * await Device.isSideLoadingEnabledAsync();
295
+ * // true or false
296
+ * ```
297
+ * @platform android
298
+ */
64
299
  export async function isSideLoadingEnabledAsync(): Promise<boolean> {
65
300
  if (!ExpoDevice.isSideLoadingEnabledAsync) {
66
301
  throw new UnavailabilityError('expo-device', 'isSideLoadingEnabledAsync');
@@ -68,6 +303,24 @@ export async function isSideLoadingEnabledAsync(): Promise<boolean> {
68
303
  return await ExpoDevice.isSideLoadingEnabledAsync();
69
304
  }
70
305
 
306
+ /**
307
+ * Gets a list of features that are available on the system. The feature names are platform-specific.
308
+ * See [Android documentation](<https://developer.android.com/reference/android/content/pm/PackageManager#getSystemAvailableFeatures()>)
309
+ * to learn more about this implementation.
310
+ * @return Returns a promise that resolves to an array of strings, each of which is a platform-specific name of a feature available on the current device.
311
+ * On iOS and web, the promise always resolves to an empty array.
312
+ * @example
313
+ * ```js
314
+ * await Device.getPlatformFeaturesAsync();
315
+ * // [
316
+ * // 'android.software.adoptable_storage',
317
+ * // 'android.software.backup',
318
+ * // 'android.hardware.sensor.accelerometer',
319
+ * // 'android.hardware.touchscreen',
320
+ * // ]
321
+ * ```
322
+ * @platform android
323
+ */
71
324
  export async function getPlatformFeaturesAsync(): Promise<string[]> {
72
325
  if (!ExpoDevice.getPlatformFeaturesAsync) {
73
326
  return [];
@@ -75,6 +328,19 @@ export async function getPlatformFeaturesAsync(): Promise<string[]> {
75
328
  return await ExpoDevice.getPlatformFeaturesAsync();
76
329
  }
77
330
 
331
+ /**
332
+ * Tells if the device has a specific system feature.
333
+ * @param feature The platform-specific name of the feature to check for on the device. You can get all available system features with `Device.getSystemFeatureAsync()`.
334
+ * See [Android documentation](<https://developer.android.com/reference/android/content/pm/PackageManager#hasSystemFeature(java.lang.String)>) to view acceptable feature strings.
335
+ * @return Returns a promise that resolves to a boolean value indicating whether the device has the specified system feature.
336
+ * On iOS and web, the promise always resolves to `false`.
337
+ * @example
338
+ * ```js
339
+ * await Device.hasPlatformFeatureAsync('amazon.hardware.fire_tv');
340
+ * // true or false
341
+ * ```
342
+ * @platform android
343
+ */
78
344
  export async function hasPlatformFeatureAsync(feature: string): Promise<boolean> {
79
345
  if (!ExpoDevice.hasPlatformFeatureAsync) {
80
346
  return false;
@@ -1,7 +1,25 @@
1
+ /**
2
+ * An enum representing the different types of devices supported by Expo.
3
+ */
1
4
  export enum DeviceType {
5
+ /**
6
+ * An unrecognized device type.
7
+ */
2
8
  UNKNOWN = 0,
9
+ /**
10
+ * Mobile phone handsets, typically with a touch screen and held in one hand.
11
+ */
3
12
  PHONE,
13
+ /**
14
+ * Tablet computers, typically with a touch screen that is larger than a usual phone.
15
+ */
4
16
  TABLET,
17
+ /**
18
+ * Desktop or laptop computers, typically with a keyboard and mouse.
19
+ */
5
20
  DESKTOP,
21
+ /**
22
+ * Device with TV-based interfaces.
23
+ */
6
24
  TV,
7
25
  }
package/src/ExpoDevice.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { NativeModulesProxy } from 'expo-modules-core';
2
- export default NativeModulesProxy.ExpoDevice;
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ export default requireNativeModule('ExpoDevice');
@@ -1,11 +0,0 @@
1
- package expo.modules.device
2
-
3
- import android.content.Context
4
- import expo.modules.core.BasePackage
5
- import expo.modules.core.ExportedModule
6
-
7
- class DevicePackage : BasePackage() {
8
- override fun createExportedModules(context: Context): List<ExportedModule> {
9
- return listOf(DeviceModule(context))
10
- }
11
- }