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.
import 'package:flutter/material.dart';
import 'package:real_device/real_device.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Real Device Example',
theme: ThemeData(
colorSchemeSeed: Colors.indigo,
useMaterial3: true,
),
home: const SecurityDashboard(),
);
}
}
class SecurityDashboard extends StatefulWidget {
const SecurityDashboard({super.key});
@override
State<SecurityDashboard> createState() => _SecurityDashboardState();
}
class _SecurityDashboardState extends State<SecurityDashboard> {
DeviceSecurityReport? _report;
bool _loading = false;
String? _error;
@override
void initState() {
super.initState();
_runChecks();
}
Future<void> _runChecks() async {
setState(() {
_loading = true;
_error = null;
});
try {
final report = await RealDevice.instance.getSecurityReport();
if (!mounted) return;
setState(() {
_report = report;
_loading = false;
});
} catch (e) {
if (!mounted) return;
setState(() {
_error = e.toString();
_loading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Device Security'),
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: _loading ? null : _runChecks,
),
],
),
body: _buildBody(),
);
}
Widget _buildBody() {
if (_loading) {
return const Center(child: CircularProgressIndicator());
}
if (_error != null) {
return Center(child: Text('Error: $_error'));
}
final report = _report;
if (report == null) {
return const Center(child: Text('No data'));
}
return ListView(
padding: const EdgeInsets.all(16),
children: [
_StatusBanner(isSecure: report.isSecure),
const SizedBox(height: 16),
_SectionCard(
title: 'Device Integrity',
isSecure: report.deviceIntegrity.isSecure,
items: [
_CheckItem('Rooted', report.deviceIntegrity.isRooted, threat: true),
_CheckItem('Jailbroken', report.deviceIntegrity.isJailbroken, threat: true),
_CheckItem('Emulator', report.deviceIntegrity.isEmulator, threat: true),
_CheckItem('Simulator', report.deviceIntegrity.isSimulator, threat: true),
_CheckItem('Developer Options', report.deviceIntegrity.isDeveloperOptionsEnabled, threat: true),
_CheckItem('ADB Enabled', report.deviceIntegrity.isAdbEnabled, threat: true),
_CheckItem('Bootloader Unlocked', report.deviceIntegrity.isBootloaderUnlocked, threat: true),
_CheckItem('Custom ROM', report.deviceIntegrity.isCustomRom, threat: true),
_CheckItem('SELinux Enforcing', report.deviceIntegrity.isSeLinuxEnforcing, threat: false),
],
),
_SectionCard(
title: 'App Tampering',
isSecure: report.appTampering.isSecure,
items: [
_CheckItem('Signature Valid', report.appTampering.isSignatureValid, threat: false),
_CheckItem('Hooking Framework', report.appTampering.isHookingFrameworkDetected, threat: true),
_CheckItem('Debugger Attached', report.appTampering.isDebuggerAttached, threat: true),
_CheckItem('App Cloned', report.appTampering.isAppCloned, threat: true),
_CheckItem('Code Injection', report.appTampering.isCodeInjectionDetected, threat: true),
],
),
_SectionCard(
title: 'Network Environment',
isSecure: report.networkEnvironment.isSecure,
items: [
_CheckItem('VPN Active', report.networkEnvironment.isVpnActive, threat: true),
_CheckItem('Proxy Configured', report.networkEnvironment.isProxyConfigured, threat: true),
_CheckItem('Mock Location', report.networkEnvironment.isMockLocationEnabled, threat: true),
_CheckItem('Time Offset (ms)', report.networkEnvironment.timeManipulationOffsetMs, threat: false),
],
),
_SectionCard(
title: 'Biometric & Identity',
isSecure: report.biometricIdentity.isSecure,
items: [
_CheckItem('Biometric Hardware', report.biometricIdentity.isBiometricHardwarePresent, threat: false),
_CheckItem('Biometric Enrolled', report.biometricIdentity.isBiometricEnrolled, threat: false),
_CheckItem('Passcode Set', report.biometricIdentity.isDevicePasscodeSet, threat: false),
_CheckItem('SIM Present', report.biometricIdentity.isSimPresent, threat: false),
_CheckItem('Multiple Users', report.biometricIdentity.hasMultipleUserProfiles, threat: true),
],
),
_SectionCard(
title: 'Hardware',
isSecure: report.hardware.isSecure,
items: [
_CheckItem('External Input', report.hardware.hasExternalInputDevices, threat: false),
_CheckItem('NFC Enabled', report.hardware.isNfcEnabled, threat: false),
_CheckItem('Camera Authentic', report.hardware.isCameraAuthentic, threat: false),
],
),
],
);
}
}
class _StatusBanner extends StatelessWidget {
final bool isSecure;
const _StatusBanner({required this.isSecure});
@override
Widget build(BuildContext context) {
return Card(
color: isSecure ? Colors.green.shade50 : Colors.red.shade50,
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
isSecure ? Icons.verified_user : Icons.warning,
color: isSecure ? Colors.green : Colors.red,
size: 32,
),
const SizedBox(width: 12),
Text(
isSecure ? 'Device is Secure' : 'Security Issues Detected',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: isSecure ? Colors.green.shade800 : Colors.red.shade800,
),
),
],
),
),
);
}
}
class _CheckItem {
final String label;
final Object? value;
final bool threat;
const _CheckItem(this.label, this.value, {required this.threat});
}
class _SectionCard extends StatelessWidget {
final String title;
final bool isSecure;
final List<_CheckItem> items;
const _SectionCard({
required this.title,
required this.isSecure,
required this.items,
});
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.only(bottom: 12),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
isSecure ? Icons.check_circle : Icons.error,
color: isSecure ? Colors.green : Colors.red,
size: 20,
),
const SizedBox(width: 8),
Text(title, style: Theme.of(context).textTheme.titleMedium),
],
),
const Divider(),
...items.map((item) => Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(item.label),
_buildValue(item),
],
),
)),
],
),
),
);
}
Widget _buildValue(_CheckItem item) {
final value = item.value;
if (value == null) {
return const Text('N/A', style: TextStyle(color: Colors.grey));
}
if (value is bool) {
final isWarning = item.threat ? value : !value;
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
isWarning ? Icons.warning_amber : Icons.check,
size: 16,
color: isWarning ? Colors.orange : Colors.green,
),
const SizedBox(width: 4),
Text(
value ? 'Yes' : 'No',
style: TextStyle(
color: isWarning ? Colors.orange.shade800 : Colors.green.shade800,
fontWeight: FontWeight.w500,
),
),
],
);
}
return Text(value.toString(),
style: const TextStyle(fontWeight: FontWeight.w500));
}
}