Browse Source

add udp

dev
赵明涛 3 days ago
parent
commit
4cb51b9668
  1. 227
      DeviceUDPManager使用说明.md
  2. 4
      app/build.gradle
  3. 539
      app/src/main/java/com/ouxuan/oxface/device/DeviceUDPManager.java
  4. 314
      app/src/main/java/com/ouxuan/oxface/device/DeviceUDPManagerUsageExample.java
  5. 351
      app/src/main/java/com/ouxuan/oxface/device/UDPTestActivity.java

227
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
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
```
### 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);
```

4
app/build.gradle

@ -91,6 +91,10 @@ dependencies {
// //
implementation "com.huawei.hms:scanplus:2.12.0.301" 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' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.ext:junit:1.1.5'

539
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));
}
}
}

314
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;
}
}
}

351
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();
}
}
}
Loading…
Cancel
Save