cross_device_integrity 1.0.6
cross_device_integrity: ^1.0.6 copied to clipboard
Unified cross-platform device integrity and security detection for Flutter (Root, Jailbreak, Emulator, Frida, Magisk, Developer Mode, Mock Location, VPN, Proxy, Screen Recording).
example/lib/main.dart
import 'dart:async';
import 'package:cross_device_integrity/cross_device_integrity.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const DeviceIntegrityExampleApp());
}
class DeviceIntegrityExampleApp extends StatelessWidget {
const DeviceIntegrityExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Device Integrity Security Dashboard',
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.dark,
darkTheme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: const Color(0xFF0B111E),
colorScheme: const ColorScheme.dark(
primary: Color(0xFFFFD03C),
surface: Color(0xFF161F2E),
error: Color(0xFFF43F5E),
),
cardTheme: const CardThemeData(
color: Color(0xFF161F2E),
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16)),
side: BorderSide(color: Color(0xFF232E3F)),
),
),
),
home: const SecurityDashboardScreen(),
);
}
}
class SecurityDashboardScreen extends StatefulWidget {
const SecurityDashboardScreen({super.key});
@override
State<SecurityDashboardScreen> createState() =>
_SecurityDashboardScreenState();
}
class _SecurityDashboardScreenState extends State<SecurityDashboardScreen> {
IntegrityResult? _result;
bool _isLoading = true;
StreamSubscription<IntegrityResult>? _monitoringSubscription;
bool _isMonitoring = false;
bool _isWindowSecure = false;
bool _useStrictConfig = true;
@override
void initState() {
super.initState();
_runIntegrityChecks();
}
@override
void dispose() {
_monitoringSubscription?.cancel();
super.dispose();
}
DeviceIntegrityConfig get _currentConfig => _useStrictConfig
? DeviceIntegrityConfig.strict()
: DeviceIntegrityConfig.development();
Future<void> _runIntegrityChecks() async {
setState(() {
_isLoading = true;
});
try {
final res = await DeviceIntegrityChecker.checkAll(_currentConfig);
if (!mounted) return;
setState(() {
_result = res;
_isLoading = false;
});
} catch (_) {
if (!mounted) return;
setState(() {
_isLoading = false;
});
}
}
void _toggleMonitoring() {
if (_isMonitoring) {
_monitoringSubscription?.cancel();
setState(() {
_isMonitoring = false;
});
} else {
setState(() {
_isMonitoring = true;
});
_monitoringSubscription =
DeviceIntegrityChecker.monitorIntegrity(
interval: const Duration(seconds: 5),
config: _currentConfig,
).listen((res) {
if (!mounted) return;
setState(() {
_result = res;
});
});
}
}
Future<void> _toggleWindowSecurity(bool enable) async {
final ok = await DeviceIntegrityChecker.setWindowSecure(enable);
if (!mounted) return;
if (ok) {
setState(() {
_isWindowSecure = enable;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
enable
? '🔒 Screen protection enabled (FLAG_SECURE)'
: '🔓 Screen protection disabled',
style: TextStyle(
color: enable ? Colors.black : Colors.white,
fontWeight: FontWeight.bold,
),
),
backgroundColor:
enable ? const Color(0xFFFFD03C) : const Color(0xFF232E3F),
elevation: 0,
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
);
}
}
@override
Widget build(BuildContext context) {
final result = _result;
return Scaffold(
backgroundColor: const Color(0xFF0B111E),
appBar: AppBar(
backgroundColor: const Color(0xFF0B111E),
elevation: 0,
scrolledUnderElevation: 0,
title: Row(
children: [
Container(
padding: const EdgeInsets.all(6),
decoration: const BoxDecoration(
color: Color(0xFFFFD03C),
shape: BoxShape.circle,
),
child: const Icon(Icons.shield, color: Colors.black, size: 18),
),
const SizedBox(width: 10),
const Text(
'Device Integrity',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
color: Colors.white,
),
),
],
),
actions: [
IconButton(
icon: Icon(
_isWindowSecure ? Icons.lock : Icons.lock_open,
color:
_isWindowSecure ? const Color(0xFFFFD03C) : Colors.white54,
),
tooltip: _isWindowSecure
? 'FLAG_SECURE Active'
: 'Enable FLAG_SECURE',
onPressed: () => _toggleWindowSecurity(!_isWindowSecure),
),
IconButton(
icon: Icon(
_isMonitoring ? Icons.sensors : Icons.radar_outlined,
color: _isMonitoring ? const Color(0xFFFFD03C) : Colors.white70,
),
tooltip: _isMonitoring
? 'Monitoring Active'
: 'Start Live Monitoring',
onPressed: _toggleMonitoring,
),
IconButton(
icon: const Icon(Icons.refresh, color: Colors.white70),
tooltip: 'Run Checks',
onPressed: _runIntegrityChecks,
),
],
),
body: _isLoading
? const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(color: Color(0xFFFFD03C)),
SizedBox(height: 16),
Text(
'Analyzing Device Security Signals...',
style: TextStyle(color: Color(0xFF8A99AD)),
),
],
),
)
: RefreshIndicator(
color: const Color(0xFFFFD03C),
backgroundColor: const Color(0xFF161F2E),
onRefresh: _runIntegrityChecks,
child: ListView(
padding: const EdgeInsets.all(16),
children: [
_buildConfigSelectorCard(),
const SizedBox(height: 16),
if (result != null) ...[
_buildOverallStatusCard(result),
const SizedBox(height: 20),
const Text(
'SECURITY SIGNALS (10 CHECKS)',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
letterSpacing: 1.2,
color: Color(0xFF8A99AD),
),
),
const SizedBox(height: 12),
_buildCheckCard(
title: 'Root Detection',
subtitle:
'Android su binaries, test-keys, mount options',
icon: Icons.developer_mode,
status: result.rootStatus,
detail: result.details['root'],
),
_buildCheckCard(
title: 'Jailbreak Detection',
subtitle:
'iOS Cydia, sandbox write, dyld hooks, fork',
icon: Icons.phonelink_lock,
status: result.jailbreakStatus,
detail: result.details['jailbreak'],
),
_buildCheckCard(
title: 'Emulator Detection',
subtitle:
'QEMU, Genymotion, BlueStacks, build props',
icon: Icons.devices_other,
status: result.emulatorStatus,
detail: result.details['emulator'],
),
_buildCheckCard(
title: 'Developer Mode',
subtitle: 'ADB debugging, USB dev mode enabled',
icon: Icons.code,
status: result.developerModeStatus,
detail: result.details['developerMode'],
),
_buildCheckCard(
title: 'Mock Location',
subtitle: 'GPS spoofing, AppOps, fake providers',
icon: Icons.location_off_outlined,
status: result.mockLocationStatus,
detail: result.details['mockLocation'],
),
_buildCheckCard(
title: 'VPN Detection',
subtitle: 'Active TUN/TAP/PPP network interfaces',
icon: Icons.vpn_key_outlined,
status: result.vpnStatus,
detail: result.details['vpn'],
),
_buildCheckCard(
title: 'Proxy Detection',
subtitle: 'HTTP/HTTPS system proxy configurations',
icon: Icons.router_outlined,
status: result.proxyStatus,
detail: result.details['proxy'],
),
_buildCheckCard(
title: 'Frida Detection',
subtitle:
'Dynamic instrumentation, D-Bus ports 27042-27045',
icon: Icons.bug_report_outlined,
status: result.fridaStatus,
detail: result.details['frida'],
),
_buildCheckCard(
title: 'Magisk Detection',
subtitle:
'Systemless root framework & overlay mounts',
icon: Icons.auto_awesome,
status: result.magiskStatus,
detail: result.details['magisk'],
),
_buildCheckCard(
title: 'Screen Recording',
subtitle:
'Screen capture, mirroring, recording active',
icon: Icons.videocam_outlined,
status: result.screenRecordingStatus,
detail: result.details['screenRecording'],
),
],
],
),
),
);
}
Widget _buildConfigSelectorCard() {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: const Color(0xFF161F2E),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: const Color(0xFF232E3F)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: _useStrictConfig
? const Color(0xFFFFD03C)
: const Color(0xFF232E3F),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
_useStrictConfig
? Icons.verified_user
: Icons.build_circle_outlined,
color: _useStrictConfig ? Colors.black : Colors.white70,
size: 20,
),
),
const SizedBox(width: 12),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_useStrictConfig
? 'Strict Production Profile'
: 'Development Profile',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: Colors.white,
),
),
const SizedBox(height: 2),
Text(
_useStrictConfig
? 'All checks strictly enforced'
: 'Dev Mode & VPN allowed',
style: const TextStyle(fontSize: 12, color: Color(0xFF8A99AD)),
),
],
),
],
),
Switch(
value: _useStrictConfig,
activeThumbColor: Colors.black,
activeTrackColor: const Color(0xFFFFD03C),
inactiveThumbColor: Colors.white54,
inactiveTrackColor: const Color(0xFF232E3F),
trackOutlineColor: WidgetStateProperty.all(Colors.transparent),
onChanged: (val) {
setState(() {
_useStrictConfig = val;
});
_runIntegrityChecks();
},
),
],
),
);
}
Widget _buildOverallStatusCard(IntegrityResult result) {
final isSecure = result.isFullySecure;
final accentColor =
isSecure ? const Color(0xFFFFD03C) : const Color(0xFFF43F5E);
final borderColor =
isSecure ? const Color(0xFFFFD03C) : const Color(0xFFF43F5E);
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: const Color(0xFF161F2E),
borderRadius: BorderRadius.circular(20),
border: Border.all(color: borderColor, width: 1.5),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: isSecure
? const Color(0xFFFFD03C)
: const Color(0xFFF43F5E),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
isSecure
? Icons.check_circle_outline
: Icons.warning_amber_rounded,
color: isSecure ? Colors.black : Colors.white,
size: 24,
),
),
const SizedBox(width: 14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
isSecure ? 'ENVIRONMENT SECURE' : 'THREATS DETECTED',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: accentColor,
letterSpacing: 0.5,
),
),
const SizedBox(height: 2),
Text(
isSecure
? 'No suspicious flags or modifications found.'
: '${result.threats.length} threat signal(s) flagged.',
style: const TextStyle(
color: Color(0xFF8A99AD),
fontSize: 13,
),
),
],
),
),
],
),
if (result.threats.isNotEmpty) ...[
const SizedBox(height: 16),
const Divider(color: Color(0xFF232E3F)),
const SizedBox(height: 8),
Wrap(
spacing: 8,
runSpacing: 8,
children: result.threats
.map(
(threat) => Chip(
backgroundColor: const Color(0xFF232E3F),
side: const BorderSide(color: Color(0xFFF43F5E)),
elevation: 0,
avatar: const Icon(
Icons.security,
size: 16,
color: Color(0xFFF43F5E),
),
label: Text(
threat,
style: const TextStyle(
color: Color(0xFFF43F5E),
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
),
)
.toList(),
),
],
],
),
);
}
Widget _buildCheckCard({
required String title,
required String subtitle,
required IconData icon,
required IntegrityStatus status,
String? detail,
}) {
Color statusColor;
String statusText;
IconData statusIcon;
switch (status) {
case IntegrityStatus.secure:
statusColor = const Color(0xFFFFD03C);
statusText = 'SECURE';
statusIcon = Icons.check_circle;
break;
case IntegrityStatus.compromised:
statusColor = const Color(0xFFF43F5E);
statusText = 'DETECTED';
statusIcon = Icons.cancel;
break;
case IntegrityStatus.unsupported:
statusColor = const Color(0xFF8A99AD);
statusText = 'N/A';
statusIcon = Icons.remove_circle_outline;
break;
case IntegrityStatus.error:
statusColor = Colors.orange;
statusText = 'ERROR';
statusIcon = Icons.error_outline;
break;
}
return Card(
margin: const EdgeInsets.only(bottom: 10),
elevation: 0,
color: const Color(0xFF161F2E),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
side: const BorderSide(color: Color(0xFF232E3F)),
),
child: Theme(
data: Theme.of(context).copyWith(
dividerColor: Colors.transparent,
),
child: ExpansionTile(
tilePadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
leading: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: statusColor == const Color(0xFFFFD03C)
? const Color(0xFFFFD03C)
: const Color(0xFF232E3F),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
icon,
color: statusColor == const Color(0xFFFFD03C)
? Colors.black
: statusColor,
size: 22,
),
),
title: Text(
title,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
color: Colors.white,
),
),
subtitle: Text(
subtitle,
style: const TextStyle(fontSize: 12, color: Color(0xFF8A99AD)),
),
trailing: Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
decoration: BoxDecoration(
color: const Color(0xFF232E3F),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: statusColor),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(statusIcon, color: statusColor, size: 14),
const SizedBox(width: 4),
Text(
statusText,
style: TextStyle(
color: statusColor,
fontWeight: FontWeight.bold,
fontSize: 11,
),
),
],
),
),
children: [
Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
const Icon(
Icons.info_outline,
size: 16,
color: Color(0xFF8A99AD),
),
const SizedBox(width: 8),
Expanded(
child: Text(
detail ?? 'No anomaly details recorded for this signal.',
style: const TextStyle(fontSize: 12, color: Colors.white70),
),
),
],
),
),
],
),
),
);
}
}