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.
- package/CHANGELOG.md +13 -0
- package/README.md +1 -1
- package/android/build.gradle +4 -4
- package/android/src/main/java/expo/modules/device/DeviceModule.kt +84 -108
- package/build/Device.d.ts +250 -0
- package/build/Device.d.ts.map +1 -1
- package/build/Device.js +250 -0
- package/build/Device.js.map +1 -1
- package/build/Device.types.d.ts +18 -0
- package/build/Device.types.d.ts.map +1 -1
- package/build/Device.types.js +18 -0
- package/build/Device.types.js.map +1 -1
- package/build/ExpoDevice.d.ts +1 -1
- package/build/ExpoDevice.d.ts.map +1 -1
- package/build/ExpoDevice.js +2 -2
- package/build/ExpoDevice.js.map +1 -1
- package/expo-module.config.json +10 -0
- package/ios/DeviceModule.swift +95 -0
- package/ios/{EXDevice.podspec → ExpoDevice.podspec} +10 -3
- package/ios/UIDevice.swift +261 -0
- package/package.json +3 -3
- package/src/Device.ts +266 -0
- package/src/Device.types.ts +18 -0
- package/src/ExpoDevice.ts +2 -2
- package/android/src/main/java/expo/modules/device/DevicePackage.kt +0 -11
- package/ios/EXDevice/EXDevice.h +0 -21
- package/ios/EXDevice/EXDevice.m +0 -374
- package/unimodule.json +0 -4
|
@@ -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.
|
|
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.
|
|
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": "
|
|
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;
|
package/src/Device.types.ts
CHANGED
|
@@ -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 {
|
|
2
|
-
export default
|
|
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
|
-
}
|