'React Native: How can I detect if my code is running in the Simulator?
In a Obj-C iOS app I can use #if (TARGET_IPHONE_SIMULATOR) to write simulator-only code.
In react native I can use:
if (__DEV__) {
.. do something special
}
.. to detect development mode.
We can use Platform.OS === 'ios' to detect the platform (Android/iOS).
See here for more info Platform Docs
But how do we detect if the app is running in the simulator?
The reason I ask is that my app uses the camera to scan barcodes, and this isn't supported in the iOS Simulator.
Solution 1:[1]
The easiest solution I can think of, which does not require creating a native module (or modifying an existing one), would be to pass this parameter as a react component property.
In your AppDelegate where the RCTRootView is initialized, you check if it's the simulator as you would do in a regular iOS app; you then pass this info to the react root-view as its initialProperties:
BOOL isSimulator = NO;
#if TARGET_IPHONE_SIMULATOR
isSimulator = YES;
#endif
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"ReactDemo"
initialProperties:@{@"isSimulator": @(isSimulator)}
launchOptions:launchOptions];
Now you can access it in the JavaScript via the props of your react component:
this.props.isSimulator
On Android, in you MainActivity which extends ReactActivity you can use a similar approach:
import android.os.Build;
import android.os.Bundle;
public boolean isEmulator() {
return Build.FINGERPRINT.startsWith("generic")
|| Build.FINGERPRINT.startsWith("unknown")
|| Build.MODEL.contains("google_sdk")
|| Build.MODEL.contains("Emulator")
|| Build.MODEL.contains("Android SDK built for x86")
|| Build.MANUFACTURER.contains("Genymotion")
|| (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic"))
|| "google_sdk".equals(Build.PRODUCT);
}
@Override
protected Bundle getLaunchOptions() {
Bundle opts = new Bundle();
opts.putBoolean("isEmulator", isEmulator());
return opts;
}
Solution 2:[2]
If you're building a CRNA/Expo app you can use Device.isDevice
https://docs.expo.dev/versions/latest/sdk/device/#deviceisdevice
import * as Device from 'expo-device';
//....
console.log(Device.isDevice) // => false if simulator
Solution 3:[3]
Using react-native-device-info you can get the following data (executed on a simulator):
getUniqueID: DB71DCB5-6BB0-497B-BE9E-A02BCC1235B7
getInstanceID: undefined
getDeviceId: x86_64
getManufacturer: Apple
getModel: Simulator
getBrand: Apple
getSystemName: iOS
getSystemVersion: 10.1
getBundleId: org.reactjs.native.example.project
getBuildNumber: 1
getVersion: 1.0
getReadableVersion: 1.0.1
getDeviceName:MacBook Pro
getUserAgent: Mozilla/5.0 (iPhone; CPU iPhone OS 10_1 like Mac OS X) AppleWebKit/602.2.14 (KHTML, like Gecko) Mobile/14B72
getDeviceLocale: en
getDeviceCountry: US
getTimezone: America/Panama
isEmulator: true
isTablet: false
Solution 4:[4]
Currently, there isn't any way to see if you are running from a simulator in JS.
I would suggest to add the conditional TARGET_IPHONE_SIMULATOR to check in your native code (if you wrote your own module). Or perhaps use a 3rd party module that doesn't render the camera if in a simulator...ie: react-native-camera: https://github.com/lwansbrough/react-native-camera/search?utf8=%E2%9C%93&q=TARGET_IPHONE_SIMULATOR
Solution 5:[5]
import getHostForRN from 'rn-host-detect';
const IS_SIMULATOR = getHostForRN('127.0.0.1') == "localhost";
This works to differentiate my iOS simulator from my actual device because the simulator returns localhost and the iOS device returns 127.0.0.1. Have not tested it on Android but let me know if it helps you guys.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Freewalker |
| Solution 2 | |
| Solution 3 | chachan |
| Solution 4 | Dave Sibiski |
| Solution 5 | Kamen Tsvetkov |
