Last active
July 10, 2025 14:12
-
-
Save jrobinsonc/6ba25e3bc937db2972090b1689085595 to your computer and use it in GitHub Desktop.
Show details about the device
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Platform } from 'react-native'; | |
export interface DeviceInfo { | |
platform: 'ios' | 'android' | 'web'; | |
isIOS: boolean; | |
isAndroid: boolean; | |
isWeb: boolean; | |
isSimulator: boolean; | |
isEmulator: boolean; | |
isExpoApp: boolean; | |
isDevelopment: boolean; | |
deviceName?: string; | |
osVersion?: string; | |
} | |
/** | |
* Detects if the app is running in iOS Simulator | |
* This is a best-effort detection and may not be 100% reliable | |
*/ | |
const isIOSSimulator = (): boolean => { | |
if (Platform.OS !== 'ios') return false; | |
// Check if we're in development mode | |
if (__DEV__) { | |
// In development, if we're on iOS and not on a physical device, | |
// we're likely in the simulator | |
return true; | |
} | |
return false; | |
}; | |
/** | |
* Detects if the app is running in Android Emulator | |
* This is a best-effort detection and may not be 100% reliable | |
*/ | |
const isAndroidEmulator = (): boolean => { | |
if (Platform.OS !== 'android') return false; | |
// Check if we're in development mode | |
if (__DEV__) { | |
// In development, if we're on Android and not on a physical device, | |
// we're likely in the emulator | |
return true; | |
} | |
return false; | |
}; | |
/** | |
* Detects if the app is running in Expo Go app | |
* This is a best-effort detection based on environment variables and development mode | |
*/ | |
const isExpoApp = (): boolean => { | |
// In development mode, if we're not in a simulator/emulator, | |
// we're likely running in Expo Go | |
if (__DEV__) { | |
const isSimulator = isIOSSimulator(); | |
const isEmulator = isAndroidEmulator(); | |
// If we're in dev mode but not in simulator/emulator, likely Expo Go | |
if (!isSimulator && !isEmulator) { | |
return true; | |
} | |
} | |
return false; | |
}; | |
/** | |
* Gets comprehensive device information | |
* | |
* @example | |
* ```typescript | |
* import { getDeviceInfo } from '@/utils/deviceDetection'; | |
* | |
* const deviceInfo = getDeviceInfo(); | |
* | |
* if (deviceInfo.isSimulator) { | |
* console.log('Running in iOS Simulator'); | |
* } | |
* | |
* if (deviceInfo.isExpoApp) { | |
* console.log('Running in Expo Go app'); | |
* } | |
* ``` | |
*/ | |
export const getDeviceInfo = (): DeviceInfo => { | |
const platform = Platform.OS as 'ios' | 'android' | 'web'; | |
const isSimulator = isIOSSimulator(); | |
const isEmulator = isAndroidEmulator(); | |
const isExpoAppRunning = isExpoApp(); | |
// Safely get device name from Platform.constants | |
let deviceName: string | undefined; | |
if (Platform.OS === 'ios') { | |
const iosConstants = Platform.constants as Record<string, unknown>; | |
deviceName = iosConstants?.systemName as string | undefined; | |
} | |
return { | |
platform, | |
isIOS: platform === 'ios', | |
isAndroid: platform === 'android', | |
isWeb: platform === 'web', | |
isSimulator, | |
isEmulator, | |
isExpoApp: isExpoAppRunning, | |
isDevelopment: __DEV__, | |
deviceName, | |
osVersion: Platform.Version?.toString(), | |
}; | |
}; | |
/** | |
* Quick check if running in iOS Simulator | |
* | |
* @example | |
* ```typescript | |
* import { isIOSSimulatorRunning } from '@/utils/deviceDetection'; | |
* | |
* if (isIOSSimulatorRunning()) { | |
* // Do something specific for iOS Simulator | |
* } | |
* ``` | |
*/ | |
export const isIOSSimulatorRunning = (): boolean => { | |
return getDeviceInfo().isSimulator; | |
}; | |
/** | |
* Quick check if running in Android Emulator | |
* | |
* @example | |
* ```typescript | |
* import { isAndroidEmulatorRunning } from '@/utils/deviceDetection'; | |
* | |
* if (isAndroidEmulatorRunning()) { | |
* // Do something specific for Android Emulator | |
* } | |
* ``` | |
*/ | |
export const isAndroidEmulatorRunning = (): boolean => { | |
return getDeviceInfo().isEmulator; | |
}; | |
/** | |
* Quick check if running in Expo Go app | |
* | |
* @example | |
* ```typescript | |
* import { isExpoGoRunning } from '@/utils/deviceDetection'; | |
* | |
* if (isExpoGoRunning()) { | |
* // Do something specific for Expo Go | |
* } | |
* ``` | |
*/ | |
export const isExpoGoRunning = (): boolean => { | |
return getDeviceInfo().isExpoApp; | |
}; | |
/** | |
* Quick check if running in any simulator/emulator | |
* | |
* @example | |
* ```typescript | |
* import { isSimulatorOrEmulator } from '@/utils/deviceDetection'; | |
* | |
* if (isSimulatorOrEmulator()) { | |
* // Do something for any simulator/emulator | |
* } | |
* ``` | |
*/ | |
export const isSimulatorOrEmulator = (): boolean => { | |
const info = getDeviceInfo(); | |
return info.isSimulator || info.isEmulator; | |
}; | |
/** | |
* Get a human-readable description of the current environment | |
* | |
* @example | |
* ```typescript | |
* import { getEnvironmentDescription } from '@/utils/deviceDetection'; | |
* | |
* const env = getEnvironmentDescription(); | |
* console.log(`Running in: ${env}`); // "Running in: iOS Simulator" | |
* ``` | |
*/ | |
export const getEnvironmentDescription = (): string => { | |
const info = getDeviceInfo(); | |
if (info.isWeb) { | |
return 'Web Browser'; | |
} | |
if (info.isExpoApp) { | |
return 'Expo Go App'; | |
} | |
if (info.isSimulator) { | |
return 'iOS Simulator'; | |
} | |
if (info.isEmulator) { | |
return 'Android Emulator'; | |
} | |
if (info.isIOS) { | |
return 'iOS Device'; | |
} | |
if (info.isAndroid) { | |
return 'Android Device'; | |
} | |
return 'Unknown Environment'; | |
}; | |
/** | |
* Log device information to console (useful for debugging) | |
* | |
* @example | |
* ```typescript | |
* import { logDeviceInfo } from '@/utils/deviceDetection'; | |
* | |
* // Log all device information to console | |
* logDeviceInfo(); | |
* ``` | |
*/ | |
export const logDeviceInfo = (): void => { | |
const info = getDeviceInfo(); | |
console.log('🔍 Device Information:', { | |
environment: getEnvironmentDescription(), | |
platform: info.platform, | |
isDevelopment: info.isDevelopment, | |
deviceName: info.deviceName, | |
osVersion: info.osVersion, | |
}); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Constants from 'expo-constants'; | |
import * as Device from 'expo-device'; | |
import React from 'react'; | |
import { View, Text, StyleSheet } from 'react-native'; | |
import { | |
getDeviceInfo, | |
getEnvironmentDescription, | |
isExpoGoRunning, | |
isIOSSimulatorRunning, | |
} from './deviceDetection'; | |
interface DeviceInfoDisplayProps { | |
showDetails?: boolean; | |
} | |
export const DeviceInfoDisplay: React.FC<DeviceInfoDisplayProps> = ({ | |
showDetails = false, | |
}) => { | |
const deviceInfo = getDeviceInfo(); | |
const environment = getEnvironmentDescription(); | |
const isSimulator = isIOSSimulatorRunning(); | |
const isExpoApp = isExpoGoRunning(); | |
return ( | |
<View style={styles.container}> | |
<Text style={styles.title}>Device Information</Text> | |
<Text style={styles.text}> | |
Device:{' '} | |
<Text style={styles.boldText}> | |
{Device.manufacturer}: {Device.modelName} | |
</Text> | |
</Text> | |
<Text style={styles.text}> | |
Constants executionEnvironment:{' '} | |
<Text style={styles.boldText}>{Constants.executionEnvironment}</Text> | |
</Text> | |
<Text style={styles.text}> | |
Environment: <Text style={styles.boldText}>{environment}</Text> | |
</Text> | |
<Text style={styles.text}> | |
Platform: <Text style={styles.boldText}>{deviceInfo.platform}</Text> | |
</Text> | |
{showDetails && ( | |
<> | |
<Text style={styles.subtitle}>Quick Checks:</Text> | |
<Text style={styles.smallText}> | |
• iOS Simulator: {isSimulator ? '✅ Yes' : '❌ No'} | |
</Text> | |
<Text style={styles.smallText}> | |
• Expo Go App: {isExpoApp ? '✅ Yes' : '❌ No'} | |
</Text> | |
<Text style={styles.smallText}> | |
• Development Mode: {deviceInfo.isDevelopment ? '✅ Yes' : '❌ No'} | |
</Text> | |
{deviceInfo.deviceName !== undefined && | |
deviceInfo.deviceName !== '' && ( | |
<Text style={styles.smallText}> | |
• Device: {deviceInfo.deviceName} | |
</Text> | |
)} | |
{deviceInfo.osVersion !== undefined && | |
deviceInfo.osVersion !== '' && ( | |
<Text style={styles.smallText}> | |
• OS Version: {deviceInfo.osVersion} | |
</Text> | |
)} | |
</> | |
)} | |
</View> | |
); | |
}; | |
const styles = StyleSheet.create({ | |
container: { | |
margin: 8, | |
borderRadius: 8, | |
backgroundColor: '#f3f4f6', | |
padding: 16, | |
}, | |
title: { | |
marginBottom: 8, | |
fontSize: 18, | |
fontWeight: 'bold', | |
}, | |
text: { | |
marginBottom: 4, | |
fontSize: 16, | |
}, | |
boldText: { | |
fontWeight: '600', | |
}, | |
subtitle: { | |
marginTop: 8, | |
fontSize: 14, | |
fontWeight: '600', | |
}, | |
smallText: { | |
fontSize: 14, | |
}, | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { ReactNode } from 'react'; | |
import React from 'react'; | |
import { StyleSheet, Text, View } from 'react-native'; | |
import { DeviceInfoDisplay } from './DeviceInfoDisplay'; | |
import { | |
getDeviceInfo, | |
getEnvironmentDescription, | |
isExpoGoRunning, | |
isIOSSimulatorRunning, | |
isSimulatorOrEmulator, | |
logDeviceInfo, | |
} from './deviceDetection'; | |
export default function DeviceTestScreen(): ReactNode { | |
// Get device information | |
const deviceInfo = getDeviceInfo(); | |
const environment = getEnvironmentDescription(); | |
const isSimulator = isIOSSimulatorRunning(); | |
const isExpoApp = isExpoGoRunning(); | |
const isSimulatorOrEmulatorRunning = isSimulatorOrEmulator(); | |
// Log device info to console for debugging | |
React.useEffect(() => { | |
logDeviceInfo(); | |
}, []); | |
return ( | |
<View style={styles.container}> | |
<View style={styles.content}> | |
<Text style={styles.title}>Device Detection Test</Text> | |
<Text style={styles.description}> | |
This screen demonstrates how to detect if you're running in iOS | |
Simulator vs Expo Go app. | |
</Text> | |
{/* Show the device info display component */} | |
<DeviceInfoDisplay showDetails={true} /> | |
{/* Show conditional content based on environment */} | |
<Text style={styles.sectionTitle}>Conditional Content:</Text> | |
{isSimulator && ( | |
<Text style={styles.simulatorText}> | |
🎯 This content only shows in iOS Simulator | |
</Text> | |
)} | |
{isExpoApp && ( | |
<Text style={styles.expoText}> | |
📱 This content only shows in Expo Go app | |
</Text> | |
)} | |
{isSimulatorOrEmulatorRunning && ( | |
<Text style={styles.emulatorText}> | |
🖥️ This content shows in any simulator/emulator | |
</Text> | |
)} | |
{!isSimulatorOrEmulatorRunning && !isExpoApp && ( | |
<Text style={styles.deviceText}> | |
📲 This content shows on physical devices | |
</Text> | |
)} | |
{/* Show raw device info */} | |
<Text style={styles.sectionTitle}>Raw Device Info:</Text> | |
<Text style={styles.rawInfo}> | |
{JSON.stringify(deviceInfo, null, 2)} | |
</Text> | |
</View> | |
</View> | |
); | |
} | |
const styles = StyleSheet.create({ | |
container: { | |
flex: 1, | |
}, | |
content: { | |
padding: 16, | |
paddingTop: 50, | |
}, | |
title: { | |
fontSize: 20, | |
fontWeight: 'bold', | |
marginBottom: 16, | |
}, | |
description: { | |
marginBottom: 8, | |
marginTop: 16, | |
fontSize: 16, | |
lineHeight: 24, | |
}, | |
sectionTitle: { | |
marginBottom: 8, | |
marginTop: 16, | |
fontSize: 16, | |
fontWeight: '600', | |
}, | |
simulatorText: { | |
marginBottom: 8, | |
color: '#2563eb', | |
fontSize: 16, | |
}, | |
expoText: { | |
marginBottom: 8, | |
color: '#16a34a', | |
fontSize: 16, | |
}, | |
emulatorText: { | |
marginBottom: 8, | |
color: '#ea580c', | |
fontSize: 16, | |
}, | |
deviceText: { | |
marginBottom: 8, | |
color: '#9333ea', | |
fontSize: 16, | |
}, | |
rawInfo: { | |
borderRadius: 4, | |
backgroundColor: '#f3f4f6', | |
padding: 8, | |
fontSize: 12, | |
fontFamily: 'monospace', | |
}, | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"dependencies": { | |
"expo-constants": "~17.1.6", | |
"expo-device": "~7.1.4" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment