real_device 0.1.0
real_device: ^0.1.0 copied to clipboard
Comprehensive device security checks for Flutter apps — root/jailbreak, emulator, hooking frameworks, VPN, biometrics, and more.
real_device #
28 device security checks for Flutter. Detect rooted/jailbroken devices, emulators, hooking frameworks, VPN connections, biometric status, and more — in a single call or one at a time.
Screen capture, screen recording, and overlay/tapjacking detection are handled separately by no_screenshot.

Installation #
dependencies:
real_device: ^0.1.0
flutter pub get
No additional setup required. No permissions are forced — checks degrade gracefully when permissions are missing.
Usage #
Run all checks at once #
import 'package:real_device/real_device.dart';
final report = await RealDevice.instance.getSecurityReport();
if (report.isSecure) {
// All clear
} else {
// Inspect individual groups
if (!report.deviceIntegrity.isSecure) { /* rooted, emulator, etc. */ }
if (!report.appTampering.isSecure) { /* hooking, debugger, etc. */ }
if (!report.networkEnvironment.isSecure) { /* VPN, proxy, etc. */ }
}
Run a single check #
final rooted = await RealDevice.instance.isRooted;
final vpn = await RealDevice.instance.isVpnActive;
final bio = await RealDevice.instance.isBiometricEnrolled;
Skip checks you don't need #
final report = await RealDevice.instance.getSecurityReport(
config: SecurityConfig(
skipChecks: {'isVpnActive', 'isProxyConfigured'},
skipHardware: true,
),
);
Skipped fields return null in the report — they are ignored by isSecure.
Request platform attestation tokens #
// Android — returns a Play Integrity token (server-side verification is your responsibility)
final playToken = await RealDevice.instance.getPlayIntegrityToken();
// iOS — returns a DeviceCheck token
final dcToken = await RealDevice.instance.getDeviceCheckToken();
// iOS — generates an App Attest key ID
final attestKeyId = await RealDevice.instance.getAppAttestKeyId();
Security Checks #
Device Integrity #

| Check | Android | iOS | Getter |
|---|---|---|---|
| Root detection | su binary, Magisk, Superuser, build tags, RW /system, busybox | -- | isRooted |
| Jailbreak detection | -- | Cydia, suspicious files, sandbox write, dylib injection | isJailbroken |
| Emulator detection | Build props, IMEI, sensors, telephony, QEMU | -- | isEmulator |
| Simulator detection | -- | #if targetEnvironment(simulator), env vars |
isSimulator |
| Developer options | Settings.Global.DEVELOPMENT_SETTINGS_ENABLED |
-- | isDeveloperOptionsEnabled |
| USB debugging / ADB | Settings.Global.ADB_ENABLED |
-- | isAdbEnabled |
| Bootloader unlocked | ro.boot.verifiedbootstate, sys.oem_unlock_allowed |
-- | isBootloaderUnlocked |
| Custom ROM | Build fingerprint, known ROM signatures, test-keys | -- | isCustomRom |
| SELinux status | /sys/fs/selinux/enforce |
-- | isSeLinuxEnforcing |
| Play Integrity | Token via com.google.android.play:integrity |
-- | getPlayIntegrityToken() |
| DeviceCheck | -- | DCDevice.generateToken |
getDeviceCheckToken() |
| App Attest | -- | DCAppAttestService.generateKey |
getAppAttestKeyId() |
App Tampering #

| Check | Android | iOS | Getter |
|---|---|---|---|
| App signature | PackageManager.GET_SIGNATURES SHA-256 |
Receipt URL + provisioning profile | isSignatureValid |
| Hooking frameworks | Frida (port 27042, /proc/maps), Xposed, Substrate | Frida/Substrate/LibertyLite via _dyld_image_name |
isHookingFrameworkDetected |
| Debugger attached | Debug.isDebuggerConnected() |
sysctl P_TRACED flag |
isDebuggerAttached |
| App cloning | Path inspection for dual-space, user-999 | -- (always false) |
isAppCloned |
| Code injection | /proc/self/maps scan |
_dyld_image_count scan |
isCodeInjectionDetected |
Network Environment #

| Check | Android | iOS | Getter |
|---|---|---|---|
| VPN active | NetworkCapabilities.TRANSPORT_VPN |
getifaddrs() utun interfaces |
isVpnActive |
| Proxy configured | System.getProperty, ConnectivityManager |
CFNetworkCopySystemProxySettings |
isProxyConfigured |
| Mock location | ALLOW_MOCK_LOCATION, mock app detection |
-- (iOS 15+ API, no passive check) | isMockLocationEnabled |
| Time manipulation | currentTimeMillis vs elapsedRealtime |
Date() vs ProcessInfo.systemUptime |
timeManipulationOffsetMs |
Biometric & Identity #
| Check | Android | iOS | Getter |
|---|---|---|---|
| Biometric hardware | BiometricManager.canAuthenticate() |
LAContext.canEvaluatePolicy() |
isBiometricHardwarePresent |
| Biometric enrolled | BIOMETRIC_SUCCESS |
canEvaluatePolicy returns true |
isBiometricEnrolled |
| Device passcode | KeyguardManager.isDeviceSecure() |
LAContext .deviceOwnerAuthentication |
isDevicePasscodeSet |
| SIM present | TelephonyManager.getSimState() |
CTTelephonyNetworkInfo |
isSimPresent |
| Multiple users | /data/user/ directories |
-- (always false) |
hasMultipleUserProfiles |
Hardware #
| Check | Android | iOS | Getter |
|---|---|---|---|
| External input devices | InputManager.getInputDeviceIds() |
EAAccessoryManager, GCController |
hasExternalInputDevices |
| NFC status | NfcAdapter.isEnabled |
NFCNDEFReaderSession.readingAvailable |
isNfcEnabled |
| Camera authenticity | Virtual camera app detection, LENS_FACING |
AVCaptureDevice.DiscoverySession |
isCameraAuthentic |
Models #
| Model | Description |
|---|---|
DeviceSecurityReport |
Aggregates all 5 groups. isSecure is true only when every group is secure. |
DeviceIntegrityStatus |
Root, jailbreak, emulator, simulator, dev opts, ADB, bootloader, ROM, SELinux. |
AppTamperingStatus |
Signature, hooking, debugger, cloning, injection. |
NetworkEnvironmentStatus |
VPN, proxy, mock location, time offset. |
BiometricIdentityStatus |
Biometric hw/enrollment, passcode, SIM, multi-user. |
HardwareStatus |
External input, NFC, camera. |
SecurityConfig |
skipChecks (set of method names) and group-level skip flags. |
All status models use bool? fields: null = skipped or not applicable, false = checked and safe, true = threat detected (or capability present for informational checks).
Platform Notes #
- Checks not applicable to a platform return
falseornull, never throw. - Play Integrity / DeviceCheck / App Attest return tokens only — server-side verification is your responsibility.
- No permissions are requested automatically; checks degrade gracefully.
Requirements #
| Platform | Minimum |
|---|---|
| Android | SDK 24 (Android 7.0) |
| iOS | 12.0 |
Android Permissions (optional) #
No permissions are required. Some checks return limited results without:
ACCESS_NETWORK_STATE— VPN and proxy detectionREAD_PHONE_STATE— SIM detectionNFC— NFC status
iOS #
Add to Info.plist if using NFC detection:
<key>NFCReaderUsageDescription</key>
<string>NFC is used to check device capabilities.</string>
iOS plugin supports both Swift Package Manager and CocoaPods.
Related #
- no_screenshot — screen capture, recording, and overlay/tapjacking prevention.
License #
BSD 3-Clause. See LICENSE.