import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_udid/flutter_udid.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import '../utils/kr_secure_storage.dart'; import '../utils/kr_log_util.dart'; import 'package:crypto/crypto.dart'; import 'dart:convert'; /// 设备信息服务 /// 用于获取设备唯一标识和其他设备信息 class KRDeviceInfoService { static final KRDeviceInfoService _instance = KRDeviceInfoService._internal(); factory KRDeviceInfoService() => _instance; KRDeviceInfoService._internal(); final DeviceInfoPlugin _deviceInfo = DeviceInfoPlugin(); String? _deviceId; Map? _deviceDetails; // 获取设备唯一标识 String? get deviceId => _deviceId; // 获取设备详细信息 Map? get deviceDetails => _deviceDetails; /// 初始化设备信息 Future initialize() async { try { KRLogUtil.kr_i('📱 开始初始化设备信息', tag: 'KRDeviceInfoService'); _deviceId = await _getDeviceId(); _deviceDetails = await _getDeviceDetails(); if (kDebugMode) { // print('✅ 设备信息初始化成功'); // print('📱 设备ID: $_deviceId'); // print('📱 设备平台: ${getPlatformName()}'); // print('📱 设备型号: ${getDeviceModel()}'); // print('📱 系统版本: ${getOSVersion()}'); // print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); } KRLogUtil.kr_i('✅ 设备信息初始化成功', tag: 'KRDeviceInfoService'); // KRLogUtil.kr_i('📱 设备ID - $_deviceId', tag: 'KRDeviceInfoService'); // KRLogUtil.kr_i('📱 设备详情 - $_deviceDetails', tag: 'KRDeviceInfoService'); } catch (e) { if (kDebugMode) { print('❌ 设备信息初始化失败: $e'); } KRLogUtil.kr_e('❌ 设备信息初始化失败 - $e', tag: 'KRDeviceInfoService'); } } /// 获取设备唯一标识 /// 使用多因子组合策略确保唯一性和稳定性 Future _getDeviceId() async { try { String identifier; if (Platform.isAndroid) { identifier = await _getAndroidDeviceId(); } else if (Platform.isIOS) { identifier = await _getIOSDeviceId(); } else if (Platform.isMacOS) { identifier = await _getMacOSDeviceId(); } else if (Platform.isWindows) { identifier = await _getWindowsDeviceId(); } else if (Platform.isLinux) { identifier = await _getLinuxDeviceId(); } else { // Web或其他平台,使用生成的UUID identifier = await _getOrCreateStoredDeviceId(); } // 如果获取失败,使用存储的或生成新的ID if (identifier.isEmpty) { identifier = await _getOrCreateStoredDeviceId(); } return identifier; } catch (e) { if (kDebugMode) { print('❌ 获取设备ID失败: $e'); } KRLogUtil.kr_e('❌ 获取设备ID失败 - $e', tag: 'KRDeviceInfoService'); // 如果获取失败,返回存储的或生成新的ID return await _getOrCreateStoredDeviceId(); } } /// Android设备ID - 多因子组合 /// 组合: AndroidID + 设备型号 + 主板信息 + 硬件信息 Future _getAndroidDeviceId() async { try { final androidInfo = await _deviceInfo.androidInfo; // 优先使用 flutter_udid (封装了多种Android标识获取方式) String udid = await FlutterUdid.consistentUdid; // 构建多因子字符串 final factors = [ udid, androidInfo.id, // Android ID androidInfo.board, // 主板 androidInfo.bootloader, // Bootloader androidInfo.brand, // 品牌 androidInfo.device, // 设备名 androidInfo.fingerprint, // 系统指纹 androidInfo.hardware, // 硬件名 androidInfo.manufacturer, // 制造商 androidInfo.model, // 型号 androidInfo.product, // 产品名 ]; // 过滤空值并组合 final combined = factors .where((f) => f != null && f.isNotEmpty) .join('|'); // 生成SHA256哈希 final bytes = utf8.encode(combined); final hash = sha256.convert(bytes); if (kDebugMode) { print('📱 Android多因子ID生成 - 因子数: ${factors.where((f) => f != null && f.isNotEmpty).length}'); } KRLogUtil.kr_i('📱 Android多因子ID - $hash', tag: 'KRDeviceInfoService'); return hash.toString(); } catch (e) { if (kDebugMode) { print('❌ Android设备ID获取失败: $e'); } KRLogUtil.kr_e('❌ Android设备ID获取失败 - $e', tag: 'KRDeviceInfoService'); return ''; } } /// iOS设备ID - 优先使用Keychain存储的UUID(卸载重装后不变) /// iOS的identifierForVendor在所有同供应商应用卸载后会重置 /// 使用flutter_secure_storage存储到iOS Keychain,保证即使卸载重装,设备ID也不会变化 Future _getIOSDeviceId() async { try { const keychainKey = 'kr_ios_device_persistent_id'; final storage = FlutterSecureStorage(); // 1. 优先从 Keychain 读取已存储的设备ID String? storedId = await storage.read(key: keychainKey); if (storedId != null && storedId.isNotEmpty) { if (kDebugMode) { print('📱 iOS: 从 Keychain 读取已存储的设备ID'); } KRLogUtil.kr_i('📱 iOS: 使用 Keychain 中的持久化设备ID', tag: 'KRDeviceInfoService'); return storedId; } // 2. 如果 Keychain 中没有,生成新的设备ID final iosInfo = await _deviceInfo.iosInfo; String udid = await FlutterUdid.consistentUdid; final factors = [ udid, iosInfo.utsname.machine, iosInfo.model, iosInfo.systemName, ]; final combined = factors.where((f) => f.isNotEmpty).join('|'); final bytes = utf8.encode(combined); final hash = sha256.convert(bytes); final newDeviceId = hash.toString(); // 3. 保存到 Keychain await storage.write(key: keychainKey, value: newDeviceId); if (kDebugMode) { print('📱 iOS: 生成新设备ID并保存到 Keychain'); } KRLogUtil.kr_i('📱 iOS: 新设备ID已保存到 Keychain', tag: 'KRDeviceInfoService'); return newDeviceId; } catch (e) { if (kDebugMode) { print('❌ iOS设备ID获取失败: $e'); } KRLogUtil.kr_e('❌ iOS设备ID获取失败 - $e', tag: 'KRDeviceInfoService'); return ''; } } /// macOS设备ID - 使用硬件UUID Future _getMacOSDeviceId() async { try { final macInfo = await _deviceInfo.macOsInfo; // 优先使用 flutter_udid String udid = await FlutterUdid.consistentUdid; // 构建多因子字符串 final factors = [ udid, macInfo.systemGUID ?? '', // 系统GUID (最稳定) macInfo.model, // 型号 macInfo.hostName, // 主机名 macInfo.arch, // 架构 macInfo.kernelVersion, // 内核版本 ]; final combined = factors .where((f) => f.isNotEmpty) .join('|'); final bytes = utf8.encode(combined); final hash = sha256.convert(bytes); if (kDebugMode) { print('📱 macOS多因子ID生成 - 因子数: ${factors.where((f) => f.isNotEmpty).length}'); } KRLogUtil.kr_i('📱 macOS多因子ID - $hash', tag: 'KRDeviceInfoService'); return hash.toString(); } catch (e) { if (kDebugMode) { print('❌ macOS设备ID获取失败: $e'); } KRLogUtil.kr_e('❌ macOS设备ID获取失败 - $e', tag: 'KRDeviceInfoService'); return ''; } } /// Windows设备ID - 使用机器GUID /// 🔧 修复:不使用 flutter_udid,因为它会调用 wmic 命令弹出黑窗口 Future _getWindowsDeviceId() async { try { final windowsInfo = await _deviceInfo.windowsInfo; // 🔧 修复:不使用 FlutterUdid.consistentUdid // 因为它在 Windows 上会调用 "cmd.exe /c wmic csproduct get UUID" // 这个调用没有使用 CREATE_NO_WINDOW 标志,会弹出黑色命令行窗口 // 直接使用 device_info_plus 提供的信息构建唯一标识 // windowsInfo.deviceId 已经是一个稳定的设备标识 // 构建多因子字符串 final factors = [ windowsInfo.deviceId, // 设备ID (最稳定,来自注册表 MachineGuid) windowsInfo.computerName, // 计算机名 windowsInfo.productName, // 产品名 windowsInfo.numberOfCores.toString(), // CPU核心数 windowsInfo.systemMemoryInMegabytes.toString(), // 内存大小 ]; final combined = factors .where((f) => f.isNotEmpty) .join('|'); final bytes = utf8.encode(combined); final hash = sha256.convert(bytes); if (kDebugMode) { print('📱 Windows多因子ID生成 - 因子数: ${factors.where((f) => f.isNotEmpty).length}'); } KRLogUtil.kr_i('📱 Windows多因子ID - $hash', tag: 'KRDeviceInfoService'); return hash.toString(); } catch (e) { if (kDebugMode) { print('❌ Windows设备ID获取失败: $e'); } KRLogUtil.kr_e('❌ Windows设备ID获取失败 - $e', tag: 'KRDeviceInfoService'); return ''; } } /// Linux设备ID - 使用machine-id Future _getLinuxDeviceId() async { try { final linuxInfo = await _deviceInfo.linuxInfo; // 优先使用 flutter_udid String udid = await FlutterUdid.consistentUdid; // 构建多因子字符串 final factors = [ udid, linuxInfo.machineId ?? '', // Machine ID (最稳定) linuxInfo.id, // 发行版ID linuxInfo.name, // 发行版名称 linuxInfo.version ?? '', // 版本 linuxInfo.variant ?? '', // 变体 ]; final combined = factors .where((f) => f.isNotEmpty) .join('|'); final bytes = utf8.encode(combined); final hash = sha256.convert(bytes); if (kDebugMode) { print('📱 Linux多因子ID生成 - 因子数: ${factors.where((f) => f.isNotEmpty).length}'); } KRLogUtil.kr_i('📱 Linux多因子ID - $hash', tag: 'KRDeviceInfoService'); return hash.toString(); } catch (e) { if (kDebugMode) { print('❌ Linux设备ID获取失败: $e'); } KRLogUtil.kr_e('❌ Linux设备ID获取失败 - $e', tag: 'KRDeviceInfoService'); return ''; } } /// 获取或创建存储的设备ID Future _getOrCreateStoredDeviceId() async { try { const key = 'kr_device_unique_id'; final storage = KRSecureStorage(); String? storedId = await storage.kr_readData(key: key); if (storedId == null || storedId.isEmpty) { // 生成新的UUID storedId = _generateUniqueId(); await storage.kr_saveData(key: key, value: storedId); if (kDebugMode) { print('📱 生成新的设备ID: $storedId'); } KRLogUtil.kr_i('📱 生成新的设备ID - $storedId', tag: 'KRDeviceInfoService'); } else { if (kDebugMode) { print('📱 使用存储的设备ID: $storedId'); } KRLogUtil.kr_i('📱 使用存储的设备ID - $storedId', tag: 'KRDeviceInfoService'); } return storedId; } catch (e) { if (kDebugMode) { print('❌ 获取存储的设备ID失败: $e'); } KRLogUtil.kr_e('❌ 获取存储的设备ID失败 - $e', tag: 'KRDeviceInfoService'); return _generateUniqueId(); } } /// 生成唯一ID String _generateUniqueId() { final timestamp = DateTime.now().millisecondsSinceEpoch.toString(); final random = DateTime.now().microsecondsSinceEpoch.toString(); final combined = '$timestamp-$random'; // 使用MD5生成唯一标识 final bytes = utf8.encode(combined); final digest = md5.convert(bytes); return digest.toString(); } /// 获取设备详细信息 Future> _getDeviceDetails() async { try { if (Platform.isAndroid) { final androidInfo = await _deviceInfo.androidInfo; return { 'platform': 'android', 'device': androidInfo.device, 'model': androidInfo.model, 'brand': androidInfo.brand, 'manufacturer': androidInfo.manufacturer, 'androidId': androidInfo.id, 'version': androidInfo.version.release, 'sdkInt': androidInfo.version.sdkInt, }; } else if (Platform.isIOS) { final iosInfo = await _deviceInfo.iosInfo; return { 'platform': 'ios', 'name': iosInfo.name, 'model': iosInfo.model, 'systemName': iosInfo.systemName, 'systemVersion': iosInfo.systemVersion, 'identifierForVendor': iosInfo.identifierForVendor, 'isPhysicalDevice': iosInfo.isPhysicalDevice, }; } else if (Platform.isMacOS) { final macInfo = await _deviceInfo.macOsInfo; return { 'platform': 'macos', 'computerName': macInfo.computerName, 'model': macInfo.model, 'hostName': macInfo.hostName, 'arch': macInfo.arch, 'systemGUID': macInfo.systemGUID, }; } else if (Platform.isWindows) { final windowsInfo = await _deviceInfo.windowsInfo; return { 'platform': 'windows', 'computerName': windowsInfo.computerName, 'numberOfCores': windowsInfo.numberOfCores, 'systemMemoryInMegabytes': windowsInfo.systemMemoryInMegabytes, }; } else if (Platform.isLinux) { final linuxInfo = await _deviceInfo.linuxInfo; return { 'platform': 'linux', 'name': linuxInfo.name, 'version': linuxInfo.version, 'id': linuxInfo.id, 'machineId': linuxInfo.machineId, }; } else if (kIsWeb) { final webInfo = await _deviceInfo.webBrowserInfo; return { 'platform': 'web', 'browserName': webInfo.browserName.toString(), 'userAgent': webInfo.userAgent, 'vendor': webInfo.vendor, }; } return { 'platform': 'unknown', }; } catch (e) { if (kDebugMode) { print('❌ 获取设备详情失败: $e'); } KRLogUtil.kr_e('❌ 获取设备详情失败 - $e', tag: 'KRDeviceInfoService'); return { 'platform': 'unknown', 'error': e.toString(), }; } } /// 获取平台名称 String getPlatformName() { if (Platform.isAndroid) return 'Android'; if (Platform.isIOS) return 'iOS'; if (Platform.isMacOS) return 'macOS'; if (Platform.isWindows) return 'Windows'; if (Platform.isLinux) return 'Linux'; if (kIsWeb) return 'Web'; return 'Unknown'; } /// 获取设备型号 String getDeviceModel() { if (_deviceDetails == null) return 'Unknown'; if (Platform.isAndroid) { return '${_deviceDetails!['brand']} ${_deviceDetails!['model']}'; } else if (Platform.isIOS) { return _deviceDetails!['model'] ?? 'Unknown'; } else if (Platform.isMacOS) { return _deviceDetails!['model'] ?? 'Unknown'; } return 'Unknown'; } /// 获取操作系统版本 String getOSVersion() { if (_deviceDetails == null) return 'Unknown'; if (Platform.isAndroid) { return _deviceDetails!['version'] ?? 'Unknown'; } else if (Platform.isIOS) { return _deviceDetails!['systemVersion'] ?? 'Unknown'; } return 'Unknown'; } /// 获取User-Agent信息 String getUserAgent() { final platform = getPlatformName(); final model = getDeviceModel(); final osVersion = getOSVersion(); return 'HiVPN/1.0.0 ($platform; $model; $osVersion) Flutter'; } }