hi-client/lib/app/services/kr_device_info_service.dart
Rust 5c8f0ca1fc 1. Android: 组合多个硬件标识 + 序列号 + Build信息
2. iOS: 组合设备型号 + 系统版本 + identifierForVendor,持久化存储到钥匙串
  3. macOS: 使用硬件UUID + 序列号
  4. Windows: 使用主板UUID + CPU信息
  5. Linux: 使用machine-id + 硬件信息

(cherry picked from commit 1be3037f715548a1efa4cc5d7d204b989878557a)
2025-10-31 00:16:49 -07:00

443 lines
14 KiB
Dart

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 '../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<String, dynamic>? _deviceDetails;
// 获取设备唯一标识
String? get deviceId => _deviceId;
// 获取设备详细信息
Map<String, dynamic>? get deviceDetails => _deviceDetails;
/// 初始化设备信息
Future<void> initialize() async {
try {
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
print('📱 开始初始化设备信息服务');
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
KRLogUtil.kr_i('📱 开始初始化设备信息', tag: 'KRDeviceInfoService');
_deviceId = await _getDeviceId();
_deviceDetails = await _getDeviceDetails();
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) {
print('❌ 设备信息初始化失败: $e');
KRLogUtil.kr_e('❌ 设备信息初始化失败 - $e', tag: 'KRDeviceInfoService');
}
}
/// 获取设备唯一标识
/// 使用多因子组合策略确保唯一性和稳定性
Future<String> _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) {
print('❌ 获取设备ID失败: $e');
KRLogUtil.kr_e('❌ 获取设备ID失败 - $e', tag: 'KRDeviceInfoService');
// 如果获取失败,返回存储的或生成新的ID
return await _getOrCreateStoredDeviceId();
}
}
/// Android设备ID - 多因子组合
/// 组合: AndroidID + 设备型号 + 主板信息 + 硬件信息
Future<String> _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);
print('📱 Android多因子ID生成 - 因子数: ${factors.where((f) => f != null && f.isNotEmpty).length}');
KRLogUtil.kr_i('📱 Android多因子ID - $hash', tag: 'KRDeviceInfoService');
return hash.toString();
} catch (e) {
print('❌ Android设备ID获取失败: $e');
KRLogUtil.kr_e('❌ Android设备ID获取失败 - $e', tag: 'KRDeviceInfoService');
return '';
}
}
/// iOS设备ID - 优先使用identifierForVendor,配合持久化存储
/// iOS限制较严,无法获取IMEI等敏感信息
Future<String> _getIOSDeviceId() async {
try {
final iosInfo = await _deviceInfo.iosInfo;
// 优先使用 flutter_udid
String udid = await FlutterUdid.consistentUdid;
// 构建多因子字符串
final factors = [
udid,
iosInfo.identifierForVendor ?? '', // Vendor标识
iosInfo.model, // 型号
iosInfo.systemName, // 系统名
iosInfo.systemVersion, // 系统版本
iosInfo.name, // 设备名(如"iPhone 14 Pro")
iosInfo.utsname.machine, // 机器类型
];
final combined = factors
.where((f) => f.isNotEmpty)
.join('|');
final bytes = utf8.encode(combined);
final hash = sha256.convert(bytes);
print('📱 iOS多因子ID生成 - 因子数: ${factors.where((f) => f.isNotEmpty).length}');
KRLogUtil.kr_i('📱 iOS多因子ID - $hash', tag: 'KRDeviceInfoService');
return hash.toString();
} catch (e) {
print('❌ iOS设备ID获取失败: $e');
KRLogUtil.kr_e('❌ iOS设备ID获取失败 - $e', tag: 'KRDeviceInfoService');
return '';
}
}
/// macOS设备ID - 使用硬件UUID
Future<String> _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);
print('📱 macOS多因子ID生成 - 因子数: ${factors.where((f) => f.isNotEmpty).length}');
KRLogUtil.kr_i('📱 macOS多因子ID - $hash', tag: 'KRDeviceInfoService');
return hash.toString();
} catch (e) {
print('❌ macOS设备ID获取失败: $e');
KRLogUtil.kr_e('❌ macOS设备ID获取失败 - $e', tag: 'KRDeviceInfoService');
return '';
}
}
/// Windows设备ID - 使用机器GUID
Future<String> _getWindowsDeviceId() async {
try {
final windowsInfo = await _deviceInfo.windowsInfo;
// 优先使用 flutter_udid
String udid = await FlutterUdid.consistentUdid;
// 构建多因子字符串
final factors = [
udid,
windowsInfo.deviceId, // 设备ID
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);
print('📱 Windows多因子ID生成 - 因子数: ${factors.where((f) => f.isNotEmpty).length}');
KRLogUtil.kr_i('📱 Windows多因子ID - $hash', tag: 'KRDeviceInfoService');
return hash.toString();
} catch (e) {
print('❌ Windows设备ID获取失败: $e');
KRLogUtil.kr_e('❌ Windows设备ID获取失败 - $e', tag: 'KRDeviceInfoService');
return '';
}
}
/// Linux设备ID - 使用machine-id
Future<String> _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);
print('📱 Linux多因子ID生成 - 因子数: ${factors.where((f) => f.isNotEmpty).length}');
KRLogUtil.kr_i('📱 Linux多因子ID - $hash', tag: 'KRDeviceInfoService');
return hash.toString();
} catch (e) {
print('❌ Linux设备ID获取失败: $e');
KRLogUtil.kr_e('❌ Linux设备ID获取失败 - $e', tag: 'KRDeviceInfoService');
return '';
}
}
/// 获取或创建存储的设备ID
Future<String> _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);
print('📱 生成新的设备ID: $storedId');
KRLogUtil.kr_i('📱 生成新的设备ID - $storedId', tag: 'KRDeviceInfoService');
} else {
print('📱 使用存储的设备ID: $storedId');
KRLogUtil.kr_i('📱 使用存储的设备ID - $storedId', tag: 'KRDeviceInfoService');
}
return storedId;
} catch (e) {
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<Map<String, dynamic>> _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) {
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';
}
}