geo_integrity_score 0.0.1+1 copy "geo_integrity_score: ^0.0.1+1" to clipboard
geo_integrity_score: ^0.0.1+1 copied to clipboard

Detects spoofing risks and produces geo integrity scores from native sensor data.

example/lib/main.dart

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:geo_integrity_score/geo_integrity_score.dart';
import 'package:permission_handler/permission_handler.dart';

import 'example_data.dart';
import 'ui/log_section.dart';
import 'ui/scenario_section.dart';
import 'ui/status_section.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  StreamSubscription<DetectionResult>? _subscription;
  DetectionResult? _latestDetection;
  bool _monitoring = false;
  String? _error;
  final List<ScenarioLogEntry> _logs = <ScenarioLogEntry>[];
  bool _scenarioInProgress = false;
  TestEnvironment _selectedEnvironment = TestEnvironment.emulator;
  ExampleScenario? _activeMonitoringScenario;
  TestEnvironment? _activeMonitoringEnvironment;
  bool _permissionGranted = false;
  bool _permissionDeniedForever = false;
  bool _checkingPermissions = false;

  static const String _manualMonitoringLabel = 'Manual Monitoring';
  static const String _manualDetectLabel = 'Manual Detect Once';

  @override
  void initState() {
    super.initState();
    unawaited(_ensurePermissions());
  }

  Future<void> _toggleMonitoring() async {
    if (!await _ensurePermissionsBeforeAction()) {
      return;
    }
    if (_monitoring) {
      await _stopMonitoring();
      return;
    }

    await _startMonitoringWithPolicy(
      const MonitoringPolicy.balanced(),
      label: _manualMonitoringLabel,
      scenario: null,
      environment: _selectedEnvironment,
    );
  }

  Future<void> _stopMonitoring() async {
    final TestEnvironment environment =
        _activeMonitoringEnvironment ?? _selectedEnvironment;
    final String label =
        _activeMonitoringScenario?.name ?? _manualMonitoringLabel;

    try {
      await GeoIntegrityScore.stopMonitoring();
    } catch (error) {
      final String message = error.toString();
      setState(() {
        _error = message;
      });
      _addLogEntry(label: label, environment: environment, error: message);
    } finally {
      await _subscription?.cancel();
      _subscription = null;
      setState(() {
        _monitoring = false;
        _activeMonitoringScenario = null;
        _activeMonitoringEnvironment = null;
      });
    }
  }

  Future<void> _startMonitoringWithPolicy(
    MonitoringPolicy policy, {
    required String label,
    required ExampleScenario? scenario,
    required TestEnvironment environment,
  }) async {
    final MonitoringPolicy effectivePolicy = policy.copyWith(
      autoStopOnIdle: false,
    );
    try {
      await GeoIntegrityScore.startMonitoring(policy: effectivePolicy);
      await _subscription?.cancel();
      _subscription = GeoIntegrityScore.detectionStream.listen(
        _handleDetectionEvent,
        onError: _handleDetectionError,
      );

      setState(() {
        _monitoring = true;
        _error = null;
        _activeMonitoringScenario = scenario;
        _activeMonitoringEnvironment = environment;
      });

      _addLogEntry(
        label: label,
        environment: environment,
        monitoringStarted: true,
      );
    } catch (error) {
      final String message = error.toString();
      setState(() {
        _error = message;
      });
      _addLogEntry(label: label, environment: environment, error: message);
    }
  }

  Future<void> _runDetectOnce({ExampleScenario? scenario}) async {
    if (!await _ensurePermissionsBeforeAction()) {
      return;
    }
    final TestEnvironment environment = _selectedEnvironment;
    final MonitoringPolicy? policyOverride = scenario?.detectPolicy;
    final String label = scenario?.name ?? _manualDetectLabel;

    try {
      final result = await GeoIntegrityScore.detectOnce(
        policyOverride: policyOverride,
      );
      setState(() {
        _latestDetection = result;
        _error = null;
      });
      _addLogEntry(label: label, environment: environment, detection: result);
    } catch (error) {
      final String message = error.toString();
      setState(() {
        _error = message;
      });
      _addLogEntry(label: label, environment: environment, error: message);
    }
  }

  void _handleDetectionEvent(DetectionResult event) {
    setState(() {
      _latestDetection = event;
      _error = null;
    });

    final String label =
        _activeMonitoringScenario?.name ?? _manualMonitoringLabel;
    final TestEnvironment environment =
        _activeMonitoringEnvironment ?? _selectedEnvironment;

    _addLogEntry(label: label, environment: environment, detection: event);
  }

  void _handleDetectionError(Object error, StackTrace stackTrace) {
    final String message = error.toString();
    setState(() {
      _error = message;
    });

    final String label =
        _activeMonitoringScenario?.name ?? _manualMonitoringLabel;
    final TestEnvironment environment =
        _activeMonitoringEnvironment ?? _selectedEnvironment;

    _addLogEntry(label: label, environment: environment, error: message);
  }

  void _addLogEntry({
    required String label,
    required TestEnvironment environment,
    DetectionResult? detection,
    String? error,
    bool monitoringStarted = false,
  }) {
    setState(() {
      _logs.add(
        ScenarioLogEntry(
          timestamp: DateTime.now().toUtc(),
          label: label,
          environment: environment,
          detection: detection,
          error: error,
          monitoringStarted: monitoringStarted,
        ),
      );
      if (_logs.length > 50) {
        _logs.removeRange(0, _logs.length - 50);
      }
    });
  }

  Future<void> _runScenario(ExampleScenario scenario) async {
    if (_scenarioInProgress) {
      return;
    }

    if (!await _ensurePermissionsBeforeAction()) {
      return;
    }

    setState(() {
      _scenarioInProgress = true;
    });

    try {
      if (scenario.usesMonitoring) {
        if (_monitoring) {
          await _stopMonitoring();
        }
        await _startMonitoringWithPolicy(
          scenario.monitoringPolicy ?? const MonitoringPolicy.balanced(),
          label: scenario.name,
          scenario: scenario,
          environment: _selectedEnvironment,
        );
      } else {
        await _runDetectOnce(scenario: scenario);
      }
    } finally {
      setState(() {
        _scenarioInProgress = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: LayoutBuilder(
            builder: (BuildContext context, BoxConstraints constraints) {
              final bool wideLayout = constraints.maxWidth >= 900;
              final List<ScenarioLogEntry> recentLogs = _logs.reversed
                  .take(15)
                  .toList(growable: false);

              final StatusSectionData statusData = StatusSectionData(
                permissionGranted: _permissionGranted,
                permissionDeniedForever: _permissionDeniedForever,
                checkingPermissions: _checkingPermissions,
                monitoring: _monitoring,
                scenarioInProgress: _scenarioInProgress,
                scenarioName:
                    _activeMonitoringScenario?.name ?? _manualMonitoringLabel,
                selectedEnvironment: _selectedEnvironment,
                currentEnvironment:
                    _activeMonitoringEnvironment ?? _selectedEnvironment,
                detection: _latestDetection,
                error: _error,
              );

              final Widget statusSection = StatusSection(
                data: statusData,
                onToggleMonitoring: _toggleMonitoring,
                onDetectOnce: () => _runDetectOnce(),
                onRequestPermission: _ensurePermissions,
                onOpenSettings: openAppSettings,
                onEnvironmentChanged: (TestEnvironment value) {
                  setState(() {
                    _selectedEnvironment = value;
                  });
                },
              );

              final Widget scenarioSection = ScenarioSection(
                scenarios: kExampleScenarios,
                selectedEnvironment: _selectedEnvironment,
                permissionGranted: _permissionGranted,
                scenarioInProgress: _scenarioInProgress,
                onRunScenario: _runScenario,
              );

              final Widget logSection = LogSection(logs: recentLogs);

              final Widget content = wideLayout
                  ? Row(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: <Widget>[
                        Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: <Widget>[
                              statusSection,
                              const SizedBox(height: 12),
                              Expanded(child: logSection),
                            ],
                          ),
                        ),
                        const SizedBox(width: 12),
                        Expanded(child: scenarioSection),
                      ],
                    )
                  : Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        statusSection,
                        const SizedBox(height: 12),
                        Flexible(child: scenarioSection),
                        const SizedBox(height: 12),
                        Flexible(child: logSection),
                      ],
                    );

              return DefaultTextStyle.merge(
                style: const TextStyle(fontSize: 12),
                child: Padding(
                  padding: const EdgeInsets.all(12),
                  child: content,
                ),
              );
            },
          ),
        ),
      ),
    );
  }

  Future<void> _ensurePermissions() async {
    setState(() {
      _checkingPermissions = true;
    });

    Future<bool> checkGranted() async {
      final List<PermissionStatus> statuses = await Future.wait(
        <Future<PermissionStatus>>[
          Permission.location.status,
          Permission.locationWhenInUse.status,
        ],
      );
      return statuses.any((PermissionStatus status) => status.isGranted);
    }

    Future<bool> checkPermanentlyDenied() async {
      final List<PermissionStatus> statuses = await Future.wait(
        <Future<PermissionStatus>>[
          Permission.location.status,
          Permission.locationWhenInUse.status,
        ],
      );
      return statuses.any(
        (PermissionStatus status) => status.isPermanentlyDenied,
      );
    }

    var granted = await checkGranted();
    if (!granted) {
      await <Permission>[
        Permission.location,
        Permission.locationWhenInUse,
      ].request();
      granted = await checkGranted();
    }
    final bool permanentlyDenied = await checkPermanentlyDenied();

    if (!mounted) {
      return;
    }

    setState(() {
      _permissionGranted = granted;
      _permissionDeniedForever = permanentlyDenied;
      _checkingPermissions = false;
    });
  }

  Future<bool> _ensurePermissionsBeforeAction() async {
    if (_permissionGranted) {
      return true;
    }
    await _ensurePermissions();
    if (_permissionGranted) {
      return true;
    }
    setState(() {
      _error =
          'Location permission is required to run monitoring or detection scenarios.';
    });
    return false;
  }
}
0
likes
160
points
0
downloads
screenshot

Publisher

unverified uploader

Weekly Downloads

Detects spoofing risks and produces geo integrity scores from native sensor data.

Repository (GitHub)
View/report issues

Topics

#location #security #monitoring #fraud-detection

Documentation

API reference

License

MIT (license)

Dependencies

flutter, meta, plugin_platform_interface

More

Packages that depend on geo_integrity_score

Packages that implement geo_integrity_score