ar_tourism_flutter_unity/lib/services/online_time_service.dart
2025-05-14 17:04:13 +08:00

169 lines
4.6 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
class OnlineTimeService {
static final OnlineTimeService _instance = OnlineTimeService._internal();
factory OnlineTimeService() => _instance;
OnlineTimeService._internal();
WebSocketChannel? _channel;
bool _isConnected = false;
bool _isConnecting = false;
Timer? _reconnectTimer;
StreamSubscription? _subscription;
Timer? _heartbeatTimer; // 定时发送心跳消息
// final String _baseWsUrl = 'ws://10.0.0.17:8081/websocket/online/';
final String _baseWsUrl = 'ws://14.103.162.172:8081/websocket/online/';
String? _token;
Future<String> _getWsUrl() async {
final prefs = await SharedPreferences.getInstance();
_token = prefs.getString('token') ?? '';
// 确保返回的是 ws:// 或 wss:// 协议的 WebSocket URL
// return 'ws://10.0.0.17:8081/websocket/online/$_token';
return 'ws://14.103.162.172:8081/websocket/online/$_token';
}
Future<void> initWebSocket() async {
if (_isConnected || _isConnecting) return;
try {
_isConnecting = true;
final wsUrl = await _getWsUrl();
print('尝试连接WebSocket: $wsUrl');
_channel = IOWebSocketChannel.connect(Uri.parse(wsUrl));
// final uri = Uri.parse(wsUrl).replace(
// queryParameters: {'Authorization': 'Bearer $_token'},
// );
// print('尝试连接WebSocket: $wsUrl');
// // print('header: ${uri.queryParameters}');
// _channel = IOWebSocketChannel.connect(wsUrl);
print('_channel: ${_channel}');
await _channel!.ready;
_isConnected = true;
_isConnecting = false;
print('WebSocket连接成功');
// 发送进入应用消息
_sendEnterMessage();
// 启动心跳定时器
_startHeartbeat();
// 开始监听消息
_startListening();
} catch (e, stack) {
print('WebSocket连接失败: $e\n$stack');
if (e is WebSocketChannelException) {
print('WebSocket错误详细信息: ${e.message}');
}
_isConnected = false;
_isConnecting = false;
// _scheduleReconnect();
}
}
// 启动心跳定时器,每隔五分钟发送一次消息
void _startHeartbeat() {
_heartbeatTimer?.cancel(); // 取消之前的定时器
_heartbeatTimer = Timer.periodic(Duration(minutes: 5), (timer) {
if (_isConnected) {
_sendHeartbeatMessage();
}
});
}
void _sendHeartbeatMessage() {
if (!_isConnected || _channel == null) return;
try {
final data = jsonEncode({
'duration': '3',
});
print('发送心跳消息: $data');
_channel!.sink.add(data);
} catch (e) {
print('发送心跳消息失败: $e');
}
}
void _sendEnterMessage() {
if (!_isConnected || _channel == null) return;
try {
final data = jsonEncode({
'duration': 1,
});
print('发送进入应用消息');
_channel!.sink.add(data);
} catch (e) {
print('发送进入消息失败: $e');
}
}
void _startListening() {
_subscription?.cancel();
_channel?.stream.listen(
(message) {
print('收到服务器消息: $message');
// try {
// final response = jsonDecode(message.toString());
// if (response['status'] == 'success') {
// print('服务器确认消息接收成功');
// }
// } catch (e) {
// print('解析服务器消息失败: $e');
// }
},
onError: (error) {
print('WebSocket错误: $error');
_isConnected = false;
_isConnecting = false;
// _scheduleReconnect();
},
onDone: () {
print('WebSocket连接关闭');
_isConnected = false;
_isConnecting = false;
// _scheduleReconnect();
},
cancelOnError: true,
);
}
// 关闭时发送 { "duration": "close" }
void dispose() {
print('正在关闭WebSocket连接...');
_subscription?.cancel(); // 取消监听
_reconnectTimer?.cancel();
_heartbeatTimer?.cancel(); // 取消心跳定时器
if (_isConnected && _channel != null) {
try {
final data = jsonEncode({
'duration': 2,
});
_channel!.sink.add(data);
print('发送关闭应用消息');
} catch (e) {
print('发送关闭消息失败: $e');
}
}
_channel?.sink.close();
_isConnected = false;
_isConnecting = false;
print('WebSocket连接已关闭');
}
}