ponshu-room-lite/lib/services/device_service.dart

73 lines
2.9 KiB
Dart
Raw Normal View History

2026-01-15 15:53:44 +00:00
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uuid/uuid.dart';
2026-01-15 15:53:44 +00:00
/// デバイスID取得サービス
/// レート制限・ライセンス管理のためのデバイス識別に使用
///
/// ## 安定性の保証
/// - Android: ANDROID_ID をハッシュ化して使用Factory Reset まで不変)
/// - iOS: SharedPreferences に UUID を永続化identifierForVendor は
/// 全ベンダーアプリ削除後の再インストールで変わるため不使用)
/// - その他/エラー時: SharedPreferences に UUID を永続化
2026-01-15 15:53:44 +00:00
class DeviceService {
static final DeviceInfoPlugin _deviceInfo = DeviceInfoPlugin();
static String? _cachedDeviceId;
static const _prefKey = 'ponshu_device_id';
2026-01-15 15:53:44 +00:00
/// デバイス固有のIDを取得SHA256ハッシュ化
static Future<String> getDeviceId() async {
if (_cachedDeviceId != null) return _cachedDeviceId!;
final prefs = await SharedPreferences.getInstance();
// SharedPreferencesに永続化済みならそれを使う再インストール後も同じIDを返す
final stored = prefs.getString(_prefKey);
if (stored != null && stored.isNotEmpty) {
_cachedDeviceId = stored;
debugPrint('[Device] Using persisted device ID: ${stored.substring(0, 8)}...');
2026-01-15 15:53:44 +00:00
return _cachedDeviceId!;
}
// 初回: ハードウェアIDから生成してSharedPreferencesに保存
final id = await _generateAndPersist(prefs);
_cachedDeviceId = id;
return id;
}
static Future<String> _generateAndPersist(SharedPreferences prefs) async {
String deviceIdentifier;
2026-01-15 15:53:44 +00:00
try {
2026-01-15 15:53:44 +00:00
if (defaultTargetPlatform == TargetPlatform.android) {
final info = await _deviceInfo.androidInfo;
// ANDROID_ID: アプリ再インストールでは変わらない。Factory Resetで変わる。
deviceIdentifier = 'android-${info.id}';
2026-01-15 15:53:44 +00:00
} else {
// iOS / その他: UUIDを生成して永続化
// identifierForVendor は全ベンダーアプリ削除後の再インストールで変わるため不使用
deviceIdentifier = 'uuid-${const Uuid().v4()}';
2026-01-15 15:53:44 +00:00
}
} catch (e) {
debugPrint('[Device] Failed to get hardware ID, using UUID fallback: $e');
deviceIdentifier = 'fallback-${const Uuid().v4()}';
2026-01-15 15:53:44 +00:00
}
final id = sha256.convert(utf8.encode(deviceIdentifier)).toString();
await prefs.setString(_prefKey, id);
debugPrint('[Device] Generated and persisted device ID: ${id.substring(0, 8)}...');
return id;
2026-01-15 15:53:44 +00:00
}
/// デバイス情報をリセット(テスト用)
static Future<void> reset() async {
2026-01-15 15:53:44 +00:00
_cachedDeviceId = null;
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_prefKey);
2026-01-15 15:53:44 +00:00
}
}