import 'dart:convert'; import 'package:crypto/crypto.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/foundation.dart'; /// デバイスID取得サービス /// レート制限のためのデバイス識別に使用 class DeviceService { static final DeviceInfoPlugin _deviceInfo = DeviceInfoPlugin(); static String? _cachedDeviceId; /// デバイス固有のIDを取得(SHA256ハッシュ化) static Future getDeviceId() async { // キャッシュがあれば返す if (_cachedDeviceId != null) { return _cachedDeviceId!; } try { String deviceIdentifier; if (defaultTargetPlatform == TargetPlatform.android) { final androidInfo = await _deviceInfo.androidInfo; // Android IDを使用(アプリ再インストールでも同じIDを維持) deviceIdentifier = androidInfo.id; } else if (defaultTargetPlatform == TargetPlatform.iOS) { final iosInfo = await _deviceInfo.iosInfo; // identifierForVendor(アプリ再インストールで変わる可能性あり) deviceIdentifier = iosInfo.identifierForVendor ?? 'unknown-ios'; } else { // その他のプラットフォーム deviceIdentifier = 'unknown-platform'; } // SHA256ハッシュ化(64文字の固定長文字列) final bytes = utf8.encode(deviceIdentifier); final digest = sha256.convert(bytes); _cachedDeviceId = digest.toString(); debugPrint('Device ID (hashed): ${_cachedDeviceId!.substring(0, 8)}...'); return _cachedDeviceId!; } catch (e) { debugPrint('Error getting device ID: $e'); // エラー時はランダムなIDを生成(セッション中は同じIDを使用) _cachedDeviceId = sha256.convert(utf8.encode('fallback-${DateTime.now().millisecondsSinceEpoch}')).toString(); return _cachedDeviceId!; } } /// デバイス情報をリセット(テスト用) static void reset() { _cachedDeviceId = null; } }