diff --git a/DeviceUDPManager使用说明.md b/DeviceUDPManager使用说明.md
new file mode 100644
index 0000000..4d5a557
--- /dev/null
+++ b/DeviceUDPManager使用说明.md
@@ -0,0 +1,227 @@
+# DeviceUDPManager 使用说明
+
+## 概述
+`DeviceUDPManager` 是基于 KryoNet 库实现的 UDP 通信管理器,支持客户端和服务端两种模式,提供了完整的 UDP 数据收发功能。
+
+## 特性
+- ✅ 支持客户端和服务端模式
+- ✅ 自动重连机制
+- ✅ 线程安全的数据收发
+- ✅ 支持多种数据类型(String、Integer、byte[]等)
+- ✅ 完整的事件回调机制
+- ✅ 单例模式,全局统一管理
+
+## 快速开始
+
+### 1. 依赖已添加
+在 `app/build.gradle` 中已添加必要依赖:
+```gradle
+// KryoNet UDP通信库
+implementation 'com.esotericsoftware:kryonet:2.22.0-RC1'
+implementation 'com.esotericsoftware:kryo:2.24.0'
+```
+
+### 2. 权限配置
+在 `AndroidManifest.xml` 中已包含必要权限:
+```xml
+
+
+```
+
+### 3. 基本使用
+
+#### 客户端模式
+```java
+// 获取管理器实例
+DeviceUDPManager udpManager = DeviceUDPManager.getInstance();
+
+// 设置监听器
+udpManager.setMessageListener(new DeviceUDPManager.UDPMessageListener() {
+ @Override
+ public void onMessageReceived(Object message, Connection connection) {
+ Log.i("UDP", "收到消息: " + message);
+ }
+
+ @Override
+ public void onMessageSent(Object message) {
+ Log.i("UDP", "发送成功: " + message);
+ }
+
+ @Override
+ public void onMessageSendFailed(Object message, String error) {
+ Log.e("UDP", "发送失败: " + error);
+ }
+});
+
+udpManager.setConnectionStateListener(new DeviceUDPManager.ConnectionStateListener() {
+ @Override
+ public void onConnected() {
+ Log.i("UDP", "连接成功");
+ // 可以开始发送消息
+ udpManager.sendUDPMessage("Hello Server!");
+ }
+
+ @Override
+ public void onDisconnected() {
+ Log.i("UDP", "连接断开");
+ }
+
+ @Override
+ public void onConnectionFailed(String error) {
+ Log.e("UDP", "连接失败: " + error);
+ }
+
+ @Override
+ public void onReconnecting(int attempt) {
+ Log.i("UDP", "重连中,第 " + attempt + " 次");
+ }
+});
+
+// 初始化为客户端
+udpManager.initializeAsClient(context, "192.168.1.100", 54555, 54777);
+```
+
+#### 服务端模式
+```java
+// 获取管理器实例
+DeviceUDPManager udpManager = DeviceUDPManager.getInstance();
+
+// 设置监听器(同客户端)
+// ...
+
+// 初始化为服务端
+udpManager.initializeAsServer(context, 54555, 54777);
+```
+
+### 4. 发送消息
+```java
+// 发送字符串消息
+udpManager.sendUDPMessage("Hello UDP!");
+
+// 发送数字消息
+udpManager.sendUDPMessage(12345);
+
+// 发送JSON格式消息
+String jsonMsg = "{\"type\":\"status\",\"value\":\"online\"}";
+udpManager.sendUDPMessage(jsonMsg);
+
+// 服务端模式:发送消息给特定客户端
+udpManager.sendUDPMessageToConnection(connection, "Hello Client!");
+```
+
+## API 参考
+
+### 主要方法
+
+#### 初始化方法
+- `initializeAsClient(Context, String, int, int)` - 初始化为客户端
+- `initializeAsServer(Context, int, int)` - 初始化为服务端
+
+#### 消息发送
+- `sendUDPMessage(Object)` - 发送UDP消息
+- `sendUDPMessageToConnection(Connection, Object)` - 发送消息给特定连接(服务端模式)
+
+#### 状态管理
+- `isConnected()` - 获取连接状态
+- `isInitialized()` - 获取初始化状态
+- `isClientMode()` - 获取当前模式
+- `reconnect()` - 手动重连(客户端模式)
+- `stop()` - 停止UDP管理器
+- `release()` - 释放所有资源
+
+#### 配置方法
+- `setMessageListener(UDPMessageListener)` - 设置消息监听器
+- `setConnectionStateListener(ConnectionStateListener)` - 设置连接状态监听器
+- `setAutoReconnect(boolean)` - 设置自动重连
+
+### 回调接口
+
+#### UDPMessageListener
+- `onMessageReceived(Object, Connection)` - 接收到消息
+- `onMessageSent(Object)` - 消息发送成功
+- `onMessageSendFailed(Object, String)` - 消息发送失败
+
+#### ConnectionStateListener
+- `onConnected()` - 连接成功
+- `onDisconnected()` - 连接断开
+- `onConnectionFailed(String)` - 连接失败
+- `onReconnecting(int)` - 重连中
+
+## 使用场景
+
+### 1. 设备间通信
+```java
+// 设备A作为服务端
+udpManager.initializeAsServer(context, 54555, 54777);
+
+// 设备B作为客户端
+udpManager.initializeAsClient(context, "设备A的IP", 54555, 54777);
+```
+
+### 2. 命令控制
+```java
+// 发送控制命令
+udpManager.sendUDPMessage("command:restart");
+udpManager.sendUDPMessage("command:get_status");
+
+// 接收端处理
+@Override
+public void onMessageReceived(Object message, Connection connection) {
+ if (message.toString().startsWith("command:")) {
+ String command = message.toString().substring(8);
+ handleCommand(command, connection);
+ }
+}
+```
+
+### 3. 状态同步
+```java
+// 定期发送状态信息
+String status = "{\"device_id\":\"" + Build.MODEL +
+ "\",\"status\":\"online\"," +
+ "\"timestamp\":" + System.currentTimeMillis() + "}";
+udpManager.sendUDPMessage(status);
+```
+
+## 注意事项
+
+1. **线程安全**: 所有方法都是线程安全的,可以在任意线程调用
+2. **网络权限**: 确保应用具有网络访问权限
+3. **端口占用**: 避免端口冲突,确保指定端口未被其他应用使用
+4. **数据类型**: 发送的对象需要是Kryo支持的类型或已注册的自定义类型
+5. **资源释放**: 在不需要时调用 `stop()` 或 `release()` 释放资源
+6. **异常处理**: 网络操作可能失败,注意处理回调中的错误信息
+
+## 测试
+
+可以使用提供的 `UDPTestActivity` 进行功能测试:
+
+1. 在 `AndroidManifest.xml` 中注册Activity
+2. 启动Activity进行测试
+3. 可以在同一设备上启动服务端和客户端进行本地测试
+
+## 扩展
+
+### 自定义数据类型
+```java
+// 注册自定义类型
+public class CustomMessage {
+ public String type;
+ public String content;
+ public long timestamp;
+}
+
+// 在初始化时注册
+udpManager.getKryo().register(CustomMessage.class);
+```
+
+### 加密通信
+可以在发送前加密消息,接收后解密:
+```java
+// 发送加密消息
+String encrypted = encrypt(originalMessage);
+udpManager.sendUDPMessage(encrypted);
+
+// 接收解密消息
+String decrypted = decrypt(encryptedMessage);
+```
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index d4225fa..b243669 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -91,6 +91,10 @@ dependencies {
// 华为扫码库
implementation "com.huawei.hms:scanplus:2.12.0.301"
+
+ // KryoNet UDP通信库
+ implementation 'com.esotericsoftware:kryonet:2.22.0-RC1'
+ implementation 'com.esotericsoftware:kryo:2.24.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
diff --git a/app/src/main/java/com/ouxuan/oxface/device/DeviceUDPManager.java b/app/src/main/java/com/ouxuan/oxface/device/DeviceUDPManager.java
new file mode 100644
index 0000000..855ef45
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/device/DeviceUDPManager.java
@@ -0,0 +1,539 @@
+package com.ouxuan.oxface.device;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import com.esotericsoftware.kryonet.Client;
+import com.esotericsoftware.kryonet.Connection;
+import com.esotericsoftware.kryonet.Listener;
+import com.esotericsoftware.kryonet.Server;
+
+import java.io.IOException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * 设备UDP通信管理器
+ * 基于KryoNet库实现UDP数据收发功能
+ *
+ * 功能特性:
+ * - 支持UDP服务端和客户端模式
+ * - 自动重连机制
+ * - 线程安全的数据收发
+ * - 支持自定义消息类型
+ *
+ * 使用示例:
+ * DeviceUDPManager manager = DeviceUDPManager.getInstance();
+ * manager.initializeAsClient(context, "192.168.1.100", 54555, 54777);
+ * manager.sendUDPMessage("Hello World");
+ *
+ * @author AI Assistant
+ * @version 1.0
+ */
+public class DeviceUDPManager {
+
+ private static final String TAG = "DeviceUDPManager";
+ private static final int DEFAULT_TCP_PORT = 54555;
+ private static final int DEFAULT_UDP_PORT = 54777;
+ private static final int RECONNECT_DELAY = 5000; // 5秒重连延迟
+ private static final int CONNECTION_TIMEOUT = 5000; // 5秒连接超时
+
+ private static DeviceUDPManager instance;
+ private Context context;
+
+ // 网络组件
+ private Client client;
+ private Server server;
+
+ // 配置参数
+ private String serverIP;
+ private int tcpPort = DEFAULT_TCP_PORT;
+ private int udpPort = DEFAULT_UDP_PORT;
+ private boolean isClientMode = true;
+ private boolean isInitialized = false;
+ private boolean isConnected = false;
+ private boolean autoReconnect = true;
+
+ // 线程管理
+ private ExecutorService executorService;
+ private Handler mainHandler;
+
+ // 回调接口
+ private UDPMessageListener messageListener;
+ private ConnectionStateListener connectionListener;
+
+ /**
+ * UDP消息监听接口
+ */
+ public interface UDPMessageListener {
+ /**
+ * 接收到UDP消息
+ * @param message 消息内容
+ * @param connection 连接对象
+ */
+ void onMessageReceived(Object message, Connection connection);
+
+ /**
+ * UDP消息发送成功
+ * @param message 发送的消息
+ */
+ void onMessageSent(Object message);
+
+ /**
+ * UDP消息发送失败
+ * @param message 发送的消息
+ * @param error 错误信息
+ */
+ void onMessageSendFailed(Object message, String error);
+ }
+
+ /**
+ * 连接状态监听接口
+ */
+ public interface ConnectionStateListener {
+ /**
+ * 连接成功
+ */
+ void onConnected();
+
+ /**
+ * 连接断开
+ */
+ void onDisconnected();
+
+ /**
+ * 连接失败
+ * @param error 错误信息
+ */
+ void onConnectionFailed(String error);
+
+ /**
+ * 重连中
+ * @param attempt 重连次数
+ */
+ void onReconnecting(int attempt);
+ }
+
+ private DeviceUDPManager() {
+ executorService = Executors.newCachedThreadPool();
+ mainHandler = new Handler(Looper.getMainLooper());
+ }
+
+ /**
+ * 获取单例实例
+ */
+ public static synchronized DeviceUDPManager getInstance() {
+ if (instance == null) {
+ instance = new DeviceUDPManager();
+ }
+ return instance;
+ }
+
+ /**
+ * 初始化为客户端模式
+ * @param context 应用上下文
+ * @param serverIP 服务器IP地址
+ * @param tcpPort TCP端口
+ * @param udpPort UDP端口
+ */
+ public void initializeAsClient(Context context, String serverIP, int tcpPort, int udpPort) {
+ this.context = context.getApplicationContext();
+ this.serverIP = serverIP;
+ this.tcpPort = tcpPort;
+ this.udpPort = udpPort;
+ this.isClientMode = true;
+
+ Log.i(TAG, "初始化为客户端模式 - 服务器: " + serverIP + ", TCP: " + tcpPort + ", UDP: " + udpPort);
+ initializeClient();
+ }
+
+ /**
+ * 初始化为服务端模式
+ * @param context 应用上下文
+ * @param tcpPort TCP端口
+ * @param udpPort UDP端口
+ */
+ public void initializeAsServer(Context context, int tcpPort, int udpPort) {
+ this.context = context.getApplicationContext();
+ this.tcpPort = tcpPort;
+ this.udpPort = udpPort;
+ this.isClientMode = false;
+
+ Log.i(TAG, "初始化为服务端模式 - TCP: " + tcpPort + ", UDP: " + udpPort);
+ initializeServer();
+ }
+
+ /**
+ * 初始化客户端
+ */
+ private void initializeClient() {
+ executorService.execute(() -> {
+ try {
+ // 清理现有连接
+ cleanup();
+
+ // 创建客户端
+ client = new Client();
+
+ // 注册常用数据类型
+ registerCommonClasses(client.getKryo());
+
+ // 添加监听器
+ client.addListener(new Listener() {
+ @Override
+ public void connected(Connection connection) {
+ Log.i(TAG, "客户端已连接到服务器");
+ isConnected = true;
+ notifyConnectionState(true);
+ }
+
+ @Override
+ public void disconnected(Connection connection) {
+ Log.i(TAG, "客户端已断开连接");
+ isConnected = false;
+ notifyConnectionState(false);
+
+ // 自动重连
+ if (autoReconnect && isInitialized) {
+ scheduleReconnect();
+ }
+ }
+
+ @Override
+ public void received(Connection connection, Object object) {
+ Log.d(TAG, "收到UDP消息: " + object);
+ notifyMessageReceived(object, connection);
+ }
+ });
+
+ // 启动客户端
+ client.start();
+ isInitialized = true;
+
+ // 连接到服务器
+ connectToServer();
+
+ } catch (Exception e) {
+ Log.e(TAG, "初始化客户端失败", e);
+ notifyConnectionError("初始化客户端失败: " + e.getMessage());
+ }
+ });
+ }
+
+ /**
+ * 初始化服务端
+ */
+ private void initializeServer() {
+ executorService.execute(() -> {
+ try {
+ // 清理现有连接
+ cleanup();
+
+ // 创建服务端
+ server = new Server();
+
+ // 注册常用数据类型
+ registerCommonClasses(server.getKryo());
+
+ // 添加监听器
+ server.addListener(new Listener() {
+ @Override
+ public void connected(Connection connection) {
+ Log.i(TAG, "客户端已连接到服务器: " + connection.getRemoteAddressTCP());
+ isConnected = true;
+ notifyConnectionState(true);
+ }
+
+ @Override
+ public void disconnected(Connection connection) {
+ Log.i(TAG, "客户端已断开连接: " + connection.getRemoteAddressTCP());
+ // 服务端模式下不需要自动重连
+ }
+
+ @Override
+ public void received(Connection connection, Object object) {
+ Log.d(TAG, "收到UDP消息: " + object + " 来自: " + connection.getRemoteAddressTCP());
+ notifyMessageReceived(object, connection);
+ }
+ });
+
+ // 绑定端口并启动
+ server.bind(tcpPort, udpPort);
+ server.start();
+ isInitialized = true;
+ isConnected = true;
+
+ Log.i(TAG, "UDP服务器已启动 - TCP: " + tcpPort + ", UDP: " + udpPort);
+ notifyConnectionState(true);
+
+ } catch (Exception e) {
+ Log.e(TAG, "初始化服务端失败", e);
+ notifyConnectionError("初始化服务端失败: " + e.getMessage());
+ }
+ });
+ }
+
+ /**
+ * 连接到服务器(客户端模式)
+ */
+ private void connectToServer() {
+ if (!isClientMode || client == null) return;
+
+ executorService.execute(() -> {
+ try {
+ Log.i(TAG, "正在连接到服务器: " + serverIP);
+ client.connect(CONNECTION_TIMEOUT, serverIP, tcpPort, udpPort);
+ } catch (IOException e) {
+ Log.e(TAG, "连接服务器失败", e);
+ notifyConnectionError("连接服务器失败: " + e.getMessage());
+
+ // 自动重连
+ if (autoReconnect && isInitialized) {
+ scheduleReconnect();
+ }
+ }
+ });
+ }
+
+ /**
+ * 安排重连
+ */
+ private int reconnectAttempt = 0;
+ private void scheduleReconnect() {
+ if (!autoReconnect || !isInitialized) return;
+
+ reconnectAttempt++;
+ Log.i(TAG, "计划重连,第 " + reconnectAttempt + " 次尝试");
+
+ mainHandler.postDelayed(() -> {
+ if (isInitialized && !isConnected && autoReconnect) {
+ notifyReconnecting(reconnectAttempt);
+ connectToServer();
+ }
+ }, RECONNECT_DELAY);
+ }
+
+ /**
+ * 注册常用数据类型
+ */
+ private void registerCommonClasses(com.esotericsoftware.kryo.Kryo kryo) {
+ kryo.register(String.class);
+ kryo.register(Integer.class);
+ kryo.register(Long.class);
+ kryo.register(Boolean.class);
+ kryo.register(Double.class);
+ kryo.register(Float.class);
+ kryo.register(byte[].class);
+ // 可以根据需要注册更多自定义类型
+ }
+
+ /**
+ * 发送UDP消息
+ * @param message 要发送的消息
+ * @return 是否发送成功
+ */
+ public boolean sendUDPMessage(Object message) {
+ if (!isInitialized || !isConnected) {
+ Log.w(TAG, "UDP管理器未初始化或未连接,无法发送消息");
+ notifyMessageSendFailed(message, "UDP管理器未初始化或未连接");
+ return false;
+ }
+
+ executorService.execute(() -> {
+ try {
+ if (isClientMode && client != null) {
+ // 客户端模式发送
+ client.sendUDP(message);
+ Log.d(TAG, "客户端发送UDP消息: " + message);
+ notifyMessageSent(message);
+ } else if (!isClientMode && server != null) {
+ // 服务端模式广播发送
+ server.sendToAllUDP(message);
+ Log.d(TAG, "服务端广播UDP消息: " + message);
+ notifyMessageSent(message);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "发送UDP消息失败", e);
+ notifyMessageSendFailed(message, "发送失败: " + e.getMessage());
+ }
+ });
+
+ return true;
+ }
+
+ /**
+ * 发送UDP消息到指定连接(服务端模式)
+ * @param connection 目标连接
+ * @param message 要发送的消息
+ * @return 是否发送成功
+ */
+ public boolean sendUDPMessageToConnection(Connection connection, Object message) {
+ if (!isInitialized || server == null || isClientMode) {
+ Log.w(TAG, "服务端模式未初始化,无法发送消息");
+ notifyMessageSendFailed(message, "服务端模式未初始化");
+ return false;
+ }
+
+ executorService.execute(() -> {
+ try {
+ connection.sendUDP(message);
+ Log.d(TAG, "服务端发送UDP消息到连接: " + message);
+ notifyMessageSent(message);
+ } catch (Exception e) {
+ Log.e(TAG, "发送UDP消息失败", e);
+ notifyMessageSendFailed(message, "发送失败: " + e.getMessage());
+ }
+ });
+
+ return true;
+ }
+
+ /**
+ * 设置消息监听器
+ */
+ public void setMessageListener(UDPMessageListener listener) {
+ this.messageListener = listener;
+ }
+
+ /**
+ * 设置连接状态监听器
+ */
+ public void setConnectionStateListener(ConnectionStateListener listener) {
+ this.connectionListener = listener;
+ }
+
+ /**
+ * 设置自动重连
+ */
+ public void setAutoReconnect(boolean autoReconnect) {
+ this.autoReconnect = autoReconnect;
+ }
+
+ /**
+ * 获取连接状态
+ */
+ public boolean isConnected() {
+ return isConnected;
+ }
+
+ /**
+ * 获取初始化状态
+ */
+ public boolean isInitialized() {
+ return isInitialized;
+ }
+
+ /**
+ * 获取当前模式
+ */
+ public boolean isClientMode() {
+ return isClientMode;
+ }
+
+ /**
+ * 手动重连(客户端模式)
+ */
+ public void reconnect() {
+ if (isClientMode && isInitialized) {
+ Log.i(TAG, "手动重连");
+ reconnectAttempt = 0;
+ connectToServer();
+ }
+ }
+
+ /**
+ * 停止UDP管理器
+ */
+ public void stop() {
+ Log.i(TAG, "停止UDP管理器");
+ isInitialized = false;
+ autoReconnect = false;
+ cleanup();
+ }
+
+ /**
+ * 清理资源
+ */
+ private void cleanup() {
+ isConnected = false;
+
+ if (client != null) {
+ try {
+ client.stop();
+ } catch (Exception e) {
+ Log.e(TAG, "停止客户端失败", e);
+ }
+ client = null;
+ }
+
+ if (server != null) {
+ try {
+ server.stop();
+ } catch (Exception e) {
+ Log.e(TAG, "停止服务端失败", e);
+ }
+ server = null;
+ }
+ }
+
+ /**
+ * 释放所有资源
+ */
+ public void release() {
+ Log.i(TAG, "释放UDP管理器资源");
+ stop();
+
+ if (executorService != null && !executorService.isShutdown()) {
+ executorService.shutdown();
+ }
+
+ messageListener = null;
+ connectionListener = null;
+ }
+
+ // 通知方法
+ private void notifyMessageReceived(Object message, Connection connection) {
+ if (messageListener != null) {
+ mainHandler.post(() -> messageListener.onMessageReceived(message, connection));
+ }
+ }
+
+ private void notifyMessageSent(Object message) {
+ if (messageListener != null) {
+ mainHandler.post(() -> messageListener.onMessageSent(message));
+ }
+ }
+
+ private void notifyMessageSendFailed(Object message, String error) {
+ if (messageListener != null) {
+ mainHandler.post(() -> messageListener.onMessageSendFailed(message, error));
+ }
+ }
+
+ private void notifyConnectionState(boolean connected) {
+ if (connectionListener != null) {
+ mainHandler.post(() -> {
+ if (connected) {
+ reconnectAttempt = 0; // 连接成功后重置重连计数
+ connectionListener.onConnected();
+ } else {
+ connectionListener.onDisconnected();
+ }
+ });
+ }
+ }
+
+ private void notifyConnectionError(String error) {
+ if (connectionListener != null) {
+ mainHandler.post(() -> connectionListener.onConnectionFailed(error));
+ }
+ }
+
+ private void notifyReconnecting(int attempt) {
+ if (connectionListener != null) {
+ mainHandler.post(() -> connectionListener.onReconnecting(attempt));
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/device/DeviceUDPManagerUsageExample.java b/app/src/main/java/com/ouxuan/oxface/device/DeviceUDPManagerUsageExample.java
new file mode 100644
index 0000000..559a796
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/device/DeviceUDPManagerUsageExample.java
@@ -0,0 +1,314 @@
+package com.ouxuan.oxface.device;
+
+import android.content.Context;
+import android.util.Log;
+
+import com.esotericsoftware.kryonet.Connection;
+
+/**
+ * DeviceUDPManager 使用示例
+ * 展示如何在项目中初始化和使用UDP通信功能
+ *
+ * @author AI Assistant
+ * @version 1.0
+ */
+public class DeviceUDPManagerUsageExample {
+
+ private static final String TAG = "UDPManagerExample";
+ private DeviceUDPManager udpManager;
+ private Context context;
+
+ public DeviceUDPManagerUsageExample(Context context) {
+ this.context = context;
+ this.udpManager = DeviceUDPManager.getInstance();
+ }
+
+ /**
+ * 初始化为客户端模式示例
+ */
+ public void initializeAsClientExample() {
+ // 设置消息监听器
+ udpManager.setMessageListener(new DeviceUDPManager.UDPMessageListener() {
+ @Override
+ public void onMessageReceived(Object message, Connection connection) {
+ Log.i(TAG, "收到消息: " + message + " 来自: " + connection.getRemoteAddressTCP());
+
+ // 处理接收到的消息
+ if (message instanceof String) {
+ String strMessage = (String) message;
+ handleStringMessage(strMessage, connection);
+ }
+ // 可以根据需要处理其他类型的消息
+ }
+
+ @Override
+ public void onMessageSent(Object message) {
+ Log.i(TAG, "消息发送成功: " + message);
+ }
+
+ @Override
+ public void onMessageSendFailed(Object message, String error) {
+ Log.e(TAG, "消息发送失败: " + message + ", 错误: " + error);
+ }
+ });
+
+ // 设置连接状态监听器
+ udpManager.setConnectionStateListener(new DeviceUDPManager.ConnectionStateListener() {
+ @Override
+ public void onConnected() {
+ Log.i(TAG, "UDP连接成功");
+ // 连接成功后可以发送消息
+ sendTestMessage();
+ }
+
+ @Override
+ public void onDisconnected() {
+ Log.i(TAG, "UDP连接断开");
+ }
+
+ @Override
+ public void onConnectionFailed(String error) {
+ Log.e(TAG, "UDP连接失败: " + error);
+ }
+
+ @Override
+ public void onReconnecting(int attempt) {
+ Log.i(TAG, "UDP重连中,第 " + attempt + " 次尝试");
+ }
+ });
+
+ // 设置自动重连
+ udpManager.setAutoReconnect(true);
+
+ // 初始化为客户端(连接到服务器)
+ String serverIP = "192.168.1.100"; // 替换为实际的服务器IP
+ int tcpPort = 54555;
+ int udpPort = 54777;
+ udpManager.initializeAsClient(context, serverIP, tcpPort, udpPort);
+ }
+
+ /**
+ * 初始化为服务端模式示例
+ */
+ public void initializeAsServerExample() {
+ // 设置消息监听器
+ udpManager.setMessageListener(new DeviceUDPManager.UDPMessageListener() {
+ @Override
+ public void onMessageReceived(Object message, Connection connection) {
+ Log.i(TAG, "服务端收到消息: " + message + " 来自: " + connection.getRemoteAddressTCP());
+
+ // 处理接收到的消息并回复
+ if (message instanceof String) {
+ String strMessage = (String) message;
+ handleServerMessage(strMessage, connection);
+ }
+ }
+
+ @Override
+ public void onMessageSent(Object message) {
+ Log.i(TAG, "服务端消息发送成功: " + message);
+ }
+
+ @Override
+ public void onMessageSendFailed(Object message, String error) {
+ Log.e(TAG, "服务端消息发送失败: " + message + ", 错误: " + error);
+ }
+ });
+
+ // 设置连接状态监听器
+ udpManager.setConnectionStateListener(new DeviceUDPManager.ConnectionStateListener() {
+ @Override
+ public void onConnected() {
+ Log.i(TAG, "服务端已准备就绪,等待客户端连接");
+ }
+
+ @Override
+ public void onDisconnected() {
+ Log.i(TAG, "客户端断开连接");
+ }
+
+ @Override
+ public void onConnectionFailed(String error) {
+ Log.e(TAG, "服务端启动失败: " + error);
+ }
+
+ @Override
+ public void onReconnecting(int attempt) {
+ // 服务端模式下通常不需要重连
+ }
+ });
+
+ // 初始化为服务端
+ int tcpPort = 54555;
+ int udpPort = 54777;
+ udpManager.initializeAsServer(context, tcpPort, udpPort);
+ }
+
+ /**
+ * 发送测试消息
+ */
+ public void sendTestMessage() {
+ if (udpManager.isConnected()) {
+ // 发送字符串消息
+ udpManager.sendUDPMessage("Hello from Android device!");
+
+ // 发送JSON格式的消息
+ String jsonMessage = "{\"type\":\"device_status\",\"status\":\"online\",\"timestamp\":" + System.currentTimeMillis() + "}";
+ udpManager.sendUDPMessage(jsonMessage);
+
+ // 发送数字消息
+ udpManager.sendUDPMessage(12345);
+ } else {
+ Log.w(TAG, "UDP未连接,无法发送消息");
+ }
+ }
+
+ /**
+ * 处理接收到的字符串消息(客户端)
+ */
+ private void handleStringMessage(String message, Connection connection) {
+ Log.d(TAG, "处理字符串消息: " + message);
+
+ // 根据消息内容进行不同处理
+ if (message.startsWith("{")) {
+ // JSON格式消息
+ handleJsonMessage(message, connection);
+ } else if (message.equals("ping")) {
+ // 心跳消息
+ udpManager.sendUDPMessage("pong");
+ } else if (message.startsWith("command:")) {
+ // 命令消息
+ String command = message.substring(8);
+ handleCommand(command, connection);
+ } else {
+ // 普通文本消息
+ Log.i(TAG, "收到普通文本消息: " + message);
+ }
+ }
+
+ /**
+ * 处理服务端接收到的消息
+ */
+ private void handleServerMessage(String message, Connection connection) {
+ Log.d(TAG, "服务端处理消息: " + message);
+
+ // 服务端可以回复消息给特定客户端
+ if (message.equals("ping")) {
+ udpManager.sendUDPMessageToConnection(connection, "pong");
+ } else if (message.equals("get_status")) {
+ String status = "{\"server_status\":\"running\",\"timestamp\":" + System.currentTimeMillis() + "}";
+ udpManager.sendUDPMessageToConnection(connection, status);
+ } else {
+ // 回复确认消息
+ udpManager.sendUDPMessageToConnection(connection, "message_received: " + message);
+ }
+ }
+
+ /**
+ * 处理JSON格式消息
+ */
+ private void handleJsonMessage(String jsonMessage, Connection connection) {
+ try {
+ Log.d(TAG, "处理JSON消息: " + jsonMessage);
+ // 这里可以使用Gson或其他JSON库解析消息
+ // 示例:设备状态更新、配置同步等
+ } catch (Exception e) {
+ Log.e(TAG, "解析JSON消息失败", e);
+ }
+ }
+
+ /**
+ * 处理命令消息
+ */
+ private void handleCommand(String command, Connection connection) {
+ Log.d(TAG, "处理命令: " + command);
+
+ switch (command) {
+ case "restart":
+ Log.i(TAG, "收到重启命令");
+ // 执行重启逻辑
+ break;
+ case "get_config":
+ Log.i(TAG, "收到获取配置命令");
+ // 返回当前配置
+ udpManager.sendUDPMessage("{\"config\":{\"version\":\"1.0\",\"mode\":\"production\"}}");
+ break;
+ case "shutdown":
+ Log.i(TAG, "收到关闭命令");
+ // 执行关闭逻辑
+ break;
+ default:
+ Log.w(TAG, "未知命令: " + command);
+ break;
+ }
+ }
+
+ /**
+ * 手动重连
+ */
+ public void reconnect() {
+ if (udpManager.isClientMode()) {
+ udpManager.reconnect();
+ }
+ }
+
+ /**
+ * 停止UDP管理器
+ */
+ public void stop() {
+ udpManager.stop();
+ }
+
+ /**
+ * 获取连接状态
+ */
+ public boolean isConnected() {
+ return udpManager.isConnected();
+ }
+
+ /**
+ * 在Activity或Service中的使用示例
+ */
+ public static class IntegrationExample {
+
+ /**
+ * 在Application中初始化(推荐)
+ */
+ public static void initializeInApplication(Context context) {
+ DeviceUDPManagerUsageExample example = new DeviceUDPManagerUsageExample(context);
+
+ // 根据设备角色选择模式
+ boolean isServer = isCurrentDeviceServer(); // 自定义逻辑判断
+
+ if (isServer) {
+ example.initializeAsServerExample();
+ } else {
+ example.initializeAsClientExample();
+ }
+ }
+
+ /**
+ * 在Activity中使用
+ */
+ public static void useInActivity(Context context) {
+ DeviceUDPManager manager = DeviceUDPManager.getInstance();
+
+ // 检查连接状态
+ if (manager.isConnected()) {
+ // 发送设备状态消息
+ String deviceInfo = "{\"device_id\":\"" + android.os.Build.MODEL + "\",\"timestamp\":" + System.currentTimeMillis() + "}";
+ manager.sendUDPMessage(deviceInfo);
+ }
+ }
+
+ /**
+ * 判断当前设备是否应该作为服务端
+ * 这里可以根据具体业务逻辑实现
+ */
+ private static boolean isCurrentDeviceServer() {
+ // 示例:可以根据设备配置、IP地址范围、设备类型等判断
+ // 这里简单返回false,实际使用时需要根据业务需求实现
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/ouxuan/oxface/device/UDPTestActivity.java b/app/src/main/java/com/ouxuan/oxface/device/UDPTestActivity.java
new file mode 100644
index 0000000..3c03123
--- /dev/null
+++ b/app/src/main/java/com/ouxuan/oxface/device/UDPTestActivity.java
@@ -0,0 +1,351 @@
+package com.ouxuan.oxface.device;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.esotericsoftware.kryonet.Connection;
+import com.ouxuan.oxface.R;
+
+/**
+ * UDP通信测试Activity
+ * 用于测试DeviceUDPManager的功能
+ *
+ * @author AI Assistant
+ * @version 1.0
+ */
+public class UDPTestActivity extends AppCompatActivity {
+
+ private static final String TAG = "UDPTestActivity";
+
+ private DeviceUDPManager udpManager;
+ private EditText etServerIP;
+ private EditText etTcpPort;
+ private EditText etUdpPort;
+ private EditText etMessage;
+ private Button btnStartClient;
+ private Button btnStartServer;
+ private Button btnSendMessage;
+ private Button btnStop;
+ private TextView tvStatus;
+ private TextView tvLog;
+ private ScrollView scrollView;
+
+ private StringBuilder logBuilder = new StringBuilder();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // 由于这是测试Activity,我们使用简单的布局
+ initializeViews();
+
+ udpManager = DeviceUDPManager.getInstance();
+ setupUDPManager();
+ setupClickListeners();
+
+ // 设置默认值
+ etServerIP.setText("192.168.1.100");
+ etTcpPort.setText("54555");
+ etUdpPort.setText("54777");
+ etMessage.setText("Hello UDP!");
+
+ updateStatus("未连接");
+ }
+
+ /**
+ * 初始化视图(简化版,实际项目中应该使用XML布局)
+ */
+ private void initializeViews() {
+ // 这里为了演示目的使用代码创建布局
+ // 在实际项目中应该创建对应的XML布局文件
+
+ android.widget.LinearLayout mainLayout = new android.widget.LinearLayout(this);
+ mainLayout.setOrientation(android.widget.LinearLayout.VERTICAL);
+ mainLayout.setPadding(32, 32, 32, 32);
+
+ // 服务器IP输入
+ android.widget.TextView ipLabel = new android.widget.TextView(this);
+ ipLabel.setText("服务器IP:");
+ mainLayout.addView(ipLabel);
+
+ etServerIP = new EditText(this);
+ etServerIP.setHint("输入服务器IP地址");
+ mainLayout.addView(etServerIP);
+
+ // TCP端口输入
+ android.widget.TextView tcpLabel = new android.widget.TextView(this);
+ tcpLabel.setText("TCP端口:");
+ mainLayout.addView(tcpLabel);
+
+ etTcpPort = new EditText(this);
+ etTcpPort.setHint("TCP端口");
+ etTcpPort.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
+ mainLayout.addView(etTcpPort);
+
+ // UDP端口输入
+ android.widget.TextView udpLabel = new android.widget.TextView(this);
+ udpLabel.setText("UDP端口:");
+ mainLayout.addView(udpLabel);
+
+ etUdpPort = new EditText(this);
+ etUdpPort.setHint("UDP端口");
+ etUdpPort.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
+ mainLayout.addView(etUdpPort);
+
+ // 按钮布局
+ android.widget.LinearLayout buttonLayout = new android.widget.LinearLayout(this);
+ buttonLayout.setOrientation(android.widget.LinearLayout.HORIZONTAL);
+
+ btnStartClient = new Button(this);
+ btnStartClient.setText("启动客户端");
+ buttonLayout.addView(btnStartClient);
+
+ btnStartServer = new Button(this);
+ btnStartServer.setText("启动服务端");
+ buttonLayout.addView(btnStartServer);
+
+ btnStop = new Button(this);
+ btnStop.setText("停止");
+ buttonLayout.addView(btnStop);
+
+ mainLayout.addView(buttonLayout);
+
+ // 消息输入
+ android.widget.TextView msgLabel = new android.widget.TextView(this);
+ msgLabel.setText("发送消息:");
+ mainLayout.addView(msgLabel);
+
+ etMessage = new EditText(this);
+ etMessage.setHint("输入要发送的消息");
+ mainLayout.addView(etMessage);
+
+ btnSendMessage = new Button(this);
+ btnSendMessage.setText("发送消息");
+ mainLayout.addView(btnSendMessage);
+
+ // 状态显示
+ tvStatus = new TextView(this);
+ tvStatus.setText("状态: 未连接");
+ tvStatus.setTextSize(16);
+ tvStatus.setPadding(0, 20, 0, 10);
+ mainLayout.addView(tvStatus);
+
+ // 日志显示
+ android.widget.TextView logLabel = new android.widget.TextView(this);
+ logLabel.setText("日志:");
+ mainLayout.addView(logLabel);
+
+ tvLog = new TextView(this);
+ tvLog.setTextSize(12);
+ tvLog.setBackgroundColor(0xFFF0F0F0);
+ tvLog.setPadding(10, 10, 10, 10);
+ tvLog.setMaxLines(20);
+
+ scrollView = new ScrollView(this);
+ scrollView.addView(tvLog);
+ android.widget.LinearLayout.LayoutParams scrollParams = new android.widget.LinearLayout.LayoutParams(
+ android.widget.LinearLayout.LayoutParams.MATCH_PARENT, 400);
+ scrollView.setLayoutParams(scrollParams);
+ mainLayout.addView(scrollView);
+
+ setContentView(mainLayout);
+ }
+
+ /**
+ * 设置UDP管理器监听器
+ */
+ private void setupUDPManager() {
+ udpManager.setMessageListener(new DeviceUDPManager.UDPMessageListener() {
+ @Override
+ public void onMessageReceived(Object message, Connection connection) {
+ String logMsg = "收到消息: " + message + " 来自: " +
+ (connection.getRemoteAddressTCP() != null ? connection.getRemoteAddressTCP().toString() : "未知");
+ addLog(logMsg);
+ Log.i(TAG, logMsg);
+ }
+
+ @Override
+ public void onMessageSent(Object message) {
+ String logMsg = "消息发送成功: " + message;
+ addLog(logMsg);
+ Log.i(TAG, logMsg);
+ }
+
+ @Override
+ public void onMessageSendFailed(Object message, String error) {
+ String logMsg = "消息发送失败: " + message + ", 错误: " + error;
+ addLog(logMsg);
+ Log.e(TAG, logMsg);
+ showToast("发送失败: " + error);
+ }
+ });
+
+ udpManager.setConnectionStateListener(new DeviceUDPManager.ConnectionStateListener() {
+ @Override
+ public void onConnected() {
+ updateStatus("已连接");
+ addLog("UDP连接成功");
+ Log.i(TAG, "UDP连接成功");
+ showToast("连接成功");
+ }
+
+ @Override
+ public void onDisconnected() {
+ updateStatus("已断开");
+ addLog("UDP连接断开");
+ Log.i(TAG, "UDP连接断开");
+ }
+
+ @Override
+ public void onConnectionFailed(String error) {
+ updateStatus("连接失败");
+ addLog("UDP连接失败: " + error);
+ Log.e(TAG, "UDP连接失败: " + error);
+ showToast("连接失败: " + error);
+ }
+
+ @Override
+ public void onReconnecting(int attempt) {
+ updateStatus("重连中 (第" + attempt + "次)");
+ addLog("UDP重连中,第 " + attempt + " 次尝试");
+ Log.i(TAG, "UDP重连中,第 " + attempt + " 次尝试");
+ }
+ });
+
+ udpManager.setAutoReconnect(true);
+ }
+
+ /**
+ * 设置按钮点击监听器
+ */
+ private void setupClickListeners() {
+ btnStartClient.setOnClickListener(v -> startClient());
+ btnStartServer.setOnClickListener(v -> startServer());
+ btnSendMessage.setOnClickListener(v -> sendMessage());
+ btnStop.setOnClickListener(v -> stopUDP());
+ }
+
+ /**
+ * 启动客户端
+ */
+ private void startClient() {
+ String serverIP = etServerIP.getText().toString().trim();
+ String tcpPortStr = etTcpPort.getText().toString().trim();
+ String udpPortStr = etUdpPort.getText().toString().trim();
+
+ if (serverIP.isEmpty()) {
+ showToast("请输入服务器IP");
+ return;
+ }
+
+ try {
+ int tcpPort = Integer.parseInt(tcpPortStr);
+ int udpPort = Integer.parseInt(udpPortStr);
+
+ updateStatus("连接中...");
+ addLog("正在启动客户端连接到 " + serverIP + ":" + tcpPort + "/" + udpPort);
+
+ udpManager.initializeAsClient(this, serverIP, tcpPort, udpPort);
+
+ } catch (NumberFormatException e) {
+ showToast("端口号格式错误");
+ }
+ }
+
+ /**
+ * 启动服务端
+ */
+ private void startServer() {
+ String tcpPortStr = etTcpPort.getText().toString().trim();
+ String udpPortStr = etUdpPort.getText().toString().trim();
+
+ try {
+ int tcpPort = Integer.parseInt(tcpPortStr);
+ int udpPort = Integer.parseInt(udpPortStr);
+
+ updateStatus("启动中...");
+ addLog("正在启动服务端,端口: " + tcpPort + "/" + udpPort);
+
+ udpManager.initializeAsServer(this, tcpPort, udpPort);
+
+ } catch (NumberFormatException e) {
+ showToast("端口号格式错误");
+ }
+ }
+
+ /**
+ * 发送消息
+ */
+ private void sendMessage() {
+ String message = etMessage.getText().toString().trim();
+
+ if (message.isEmpty()) {
+ showToast("请输入要发送的消息");
+ return;
+ }
+
+ if (!udpManager.isConnected()) {
+ showToast("UDP未连接,无法发送消息");
+ return;
+ }
+
+ addLog("发送消息: " + message);
+ udpManager.sendUDPMessage(message);
+
+ // 清空输入框
+ etMessage.setText("");
+ }
+
+ /**
+ * 停止UDP
+ */
+ private void stopUDP() {
+ updateStatus("已停止");
+ addLog("停止UDP服务");
+ udpManager.stop();
+ showToast("UDP服务已停止");
+ }
+
+ /**
+ * 更新状态显示
+ */
+ private void updateStatus(String status) {
+ runOnUiThread(() -> tvStatus.setText("状态: " + status));
+ }
+
+ /**
+ * 添加日志
+ */
+ private void addLog(String log) {
+ runOnUiThread(() -> {
+ String timestamp = java.text.DateFormat.getTimeInstance().format(new java.util.Date());
+ logBuilder.append("[").append(timestamp).append("] ").append(log).append("\n");
+ tvLog.setText(logBuilder.toString());
+
+ // 自动滚动到底部
+ scrollView.post(() -> scrollView.fullScroll(ScrollView.FOCUS_DOWN));
+ });
+ }
+
+ /**
+ * 显示Toast消息
+ */
+ private void showToast(String message) {
+ runOnUiThread(() -> Toast.makeText(this, message, Toast.LENGTH_SHORT).show());
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (udpManager != null) {
+ udpManager.stop();
+ }
+ }
+}
\ No newline at end of file