跨设备消息发送:基于HarmonyOS分布式能力的多设备协同实现
跨设备的实时文本消息发送与接收设备连接状态的实时监控与显示完整的消息历史记录可靠的传输机制通过借鉴游戏中的多设备同步技术,我们构建了一个稳定高效的跨设备通信系统。跨设备文件共享多设备协同办公分布式计算任务分配智能家居设备控制消息加密传输大文件分片传输消息已读回执设备间直接P2P通信这个项目展示了HarmonyOS分布式能力的强大之处,为开发更复杂的跨设备应用奠定了基础。
·
跨设备消息发送:基于HarmonyOS分布式能力的多设备协同实现
一、项目概述
本文基于HarmonyOS分布式能力,实现手机和平板间的简单文本消息同步功能。项目借鉴《鸿蒙跨端U同步》中游戏多设备玩家状态同步的设计思想,构建了一个轻量级的跨设备消息发送系统,支持实时文本消息同步、设备状态感知和消息历史记录等功能。
二、架构设计
+---------------------+ +---------------------+
| 手机设备 |<----->| 平板设备 |
+----------+----------+ +----------+----------+
| |
+----------v----------+ +----------v----------+
| 消息发送UI组件 | | 消息接收UI组件 |
+----------+----------+ +----------+----------+
| |
+----------v-----------------------------v----------+
| 消息同步服务 |
| (MessageSyncService) |
+----------+----------------------------------+-----+
| |
+----------v----------+ +---------v-----------+
| 分布式数据管理 | | 设备连接管理 |
| (DistributedData) | | (DeviceManager) |
+---------------------+ +---------------------+
三、核心代码实现
1. 消息同步服务实现
public class MessageSyncService {
private static final String TAG = "MessageSyncService";
private static final String MESSAGE_CHANNEL = "cross_device_messages";
private static final String DEVICE_INFO_KEY = "connected_devices";
private static MessageSyncService instance;
private DistributedDataManager dataManager;
private List<Message> messageHistory = new ArrayList<>();
private List<DeviceInfo> connectedDevices = new ArrayList<>();
private MessageListener messageListener;
private DeviceStateListener deviceListener;
private MessageSyncService(Context context) {
this.dataManager = DistributedDataManagerFactory.getInstance()
.createDistributedDataManager(context);
initDeviceListener();
}
public static synchronized MessageSyncService getInstance(Context context) {
if (instance == null) {
instance = new MessageSyncService(context);
}
return instance;
}
private void initDeviceListener() {
DeviceManager deviceManager = DeviceManager.getInstance();
deviceListener = new DeviceStateListener() {
@Override
public void onDeviceConnected(DeviceInfo device) {
connectedDevices.add(device);
syncDeviceList();
if (messageListener != null) {
messageListener.onDeviceConnected(device);
}
}
@Override
public void onDeviceDisconnected(DeviceInfo device) {
connectedDevices.remove(device);
syncDeviceList();
if (messageListener != null) {
messageListener.onDeviceDisconnected(device);
}
}
};
deviceManager.registerDeviceListener(deviceListener);
}
// 同步设备列表
private void syncDeviceList() {
JSONArray deviceArray = new JSONArray();
for (DeviceInfo device : connectedDevices) {
JSONObject deviceJson = new JSONObject();
try {
deviceJson.put("deviceId", device.getDeviceId());
deviceJson.put("deviceName", device.getDeviceName());
deviceJson.put("deviceType", device.getDeviceType());
deviceArray.put(deviceJson);
} catch (JSONException e) {
HiLog.error(TAG, "Failed to serialize device info");
}
}
dataManager.putString(DEVICE_INFO_KEY, deviceArray.toString());
}
// 发送消息
public void sendMessage(String content) {
Message message = new Message(
content,
System.currentTimeMillis(),
DistributedDeviceInfo.getLocalDeviceId(),
DistributedDeviceInfo.getLocalDeviceName()
);
messageHistory.add(message);
broadcastMessage(message);
}
// 广播消息到所有设备
private void broadcastMessage(Message message) {
JSONObject messageJson = new JSONObject();
try {
messageJson.put("content", message.getContent());
messageJson.put("timestamp", message.getTimestamp());
messageJson.put("senderId", message.getSenderId());
messageJson.put("senderName", message.getSenderName());
messageJson.put("version", getNextVersion());
} catch (JSONException e) {
HiLog.error(TAG, "Failed to serialize message");
return;
}
dataManager.putString(MESSAGE_CHANNEL, messageJson.toString());
}
// 注册消息监听器
public void registerMessageListener(MessageListener listener) {
this.messageListener = listener;
// 监听消息变化
dataManager.registerDataChangeListener(MESSAGE_CHANNEL, new DataChangeListener() {
@Override
public void onDataChanged(String deviceId, String key, String value) {
try {
JSONObject messageJson = new JSONObject(value);
Message message = new Message(
messageJson.getString("content"),
messageJson.getLong("timestamp"),
messageJson.getString("senderId"),
messageJson.getString("senderName")
);
// 避免处理自己发送的消息
if (!message.getSenderId().equals(DistributedDeviceInfo.getLocalDeviceId())) {
messageHistory.add(message);
if (messageListener != null) {
messageListener.onMessageReceived(message);
}
}
} catch (JSONException e) {
HiLog.error(TAG, "Failed to parse message: " + e.getMessage());
}
}
});
// 监听设备列表变化
dataManager.registerDataChangeListener(DEVICE_INFO_KEY, new DataChangeListener() {
@Override
public void onDataChanged(String deviceId, String key, String value) {
updateConnectedDevices(value);
}
});
}
// 更新已连接设备列表
private void updateConnectedDevices(String devicesJson) {
try {
JSONArray deviceArray = new JSONArray(devicesJson);
List<DeviceInfo> newDevices = new ArrayList<>();
for (int i = 0; i < deviceArray.length(); i++) {
JSONObject deviceJson = deviceArray.getJSONObject(i);
DeviceInfo device = new DeviceInfo(
deviceJson.getString("deviceId"),
deviceJson.getString("deviceName"),
deviceJson.getString("deviceType")
);
newDevices.add(device);
}
connectedDevices = newDevices;
if (messageListener != null) {
messageListener.onDeviceListUpdated(connectedDevices);
}
} catch (JSONException e) {
HiLog.error(TAG, "Failed to parse device list: " + e.getMessage());
}
}
// 获取消息历史
public List<Message> getMessageHistory() {
return new ArrayList<>(messageHistory);
}
// 获取已连接设备
public List<DeviceInfo> getConnectedDevices() {
return new ArrayList<>(connectedDevices);
}
// 消息数据类
public static class Message {
private String content;
private long timestamp;
private String senderId;
private String senderName;
public Message(String content, long timestamp, String senderId, String senderName) {
this.content = content;
this.timestamp = timestamp;
this.senderId = senderId;
this.senderName = senderName;
}
// getter方法省略...
}
// 设备信息类
public static class DeviceInfo {
private String deviceId;
private String deviceName;
private String deviceType;
public DeviceInfo(String deviceId, String deviceName, String deviceType) {
this.deviceId = deviceId;
this.deviceName = deviceName;
this.deviceType = deviceType;
}
// getter方法省略...
}
public interface MessageListener {
void onMessageReceived(Message message);
void onDeviceConnected(DeviceInfo device);
void onDeviceDisconnected(DeviceInfo device);
void onDeviceListUpdated(List<DeviceInfo> devices);
}
private int versionCounter = 0;
private synchronized int getNextVersion() {
return ++versionCounter;
}
}
2. 消息发送界面实现
public class MessageSenderSlice extends AbilitySlice {
private static final String TAG = "MessageSenderSlice";
private MessageSyncService messageSync;
private TextField messageInput;
private Text messageDisplay;
private Text deviceStatusDisplay;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
setUIContent(ResourceTable.Layout_message_sender_layout);
// 初始化消息同步服务
messageSync = MessageSyncService.getInstance(this);
// 获取UI组件
messageInput = (TextField) findComponentById(ResourceTable.Id_message_input);
Button sendButton = (Button) findComponentById(ResourceTable.Id_send_button);
messageDisplay = (Text) findComponentById(ResourceTable.Id_message_display);
deviceStatusDisplay = (Text) findComponentById(ResourceTable.Id_device_status);
// 设置发送按钮点击事件
sendButton.setClickedListener(component -> {
String message = messageInput.getText();
if (!message.isEmpty()) {
messageSync.sendMessage(message);
messageInput.setText("");
updateMessageDisplay();
}
});
// 注册消息监听器
messageSync.registerMessageListener(new MessageSyncService.MessageListener() {
@Override
public void onMessageReceived(MessageSyncService.Message message) {
getUITaskDispatcher().asyncDispatch(() -> {
updateMessageDisplay();
});
}
@Override
public void onDeviceConnected(MessageSyncService.DeviceInfo device) {
getUITaskDispatcher().asyncDispatch(() -> {
updateDeviceStatus();
showToast(device.getDeviceName() + " 已连接");
});
}
@Override
public void onDeviceDisconnected(MessageSyncService.DeviceInfo device) {
getUITaskDispatcher().asyncDispatch(() -> {
updateDeviceStatus();
showToast(device.getDeviceName() + " 已断开");
});
}
@Override
public void onDeviceListUpdated(List<MessageSyncService.DeviceInfo> devices) {
getUITaskDispatcher().asyncDispatch(() -> {
updateDeviceStatus();
});
}
});
// 初始更新显示
updateMessageDisplay();
updateDeviceStatus();
}
private void updateMessageDisplay() {
StringBuilder builder = new StringBuilder();
List<MessageSyncService.Message> messages = messageSync.getMessageHistory();
for (MessageSyncService.Message message : messages) {
String prefix = message.getSenderId().equals(DistributedDeviceInfo.getLocalDeviceId())
? "我: " : message.getSenderName() + ": ";
builder.append(prefix).append(message.getContent()).append("\n");
}
messageDisplay.setText(builder.toString());
}
private void updateDeviceStatus() {
StringBuilder builder = new StringBuilder("已连接设备:\n");
List<MessageSyncService.DeviceInfo> devices = messageSync.getConnectedDevices();
for (MessageSyncService.DeviceInfo device : devices) {
builder.append("- ").append(device.getDeviceName())
.append(" (").append(device.getDeviceType()).append(")\n");
}
deviceStatusDisplay.setText(builder.toString());
}
private void showToast(String message) {
new ToastDialog(getContext())
.setText(message)
.show();
}
}
3. XML布局文件
<!-- 消息发送界面布局 message_sender_layout.xml -->
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:width="match_parent"
ohos:height="match_parent"
ohos:orientation="vertical"
ohos:padding="24vp">
<Text
ohos:width="match_parent"
ohos:height="wrap_content"
ohos:text="跨设备消息发送"
ohos:text_size="24fp"
ohos:margin_bottom="16vp"/>
<TextField
ohos:id="$+id:message_input"
ohos:width="match_parent"
ohos:height="80vp"
ohos:hint="输入要发送的消息"
ohos:margin_bottom="16vp"/>
<Button
ohos:id="$+id:send_button"
ohos:width="match_parent"
ohos:height="60vp"
ohos:text="发送"
ohos:margin_bottom="16vp"/>
<ScrollView
ohos:width="match_parent"
ohos:height="200vp"
ohos:margin_bottom="16vp">
<Text
ohos:id="$+id:message_display"
ohos:width="match_parent"
ohos:height="match_parent"
ohos:text="消息将显示在这里..."/>
</ScrollView>
<ScrollView
ohos:width="match_parent"
ohos:height="200vp">
<Text
ohos:id="$+id:device_status"
ohos:width="match_parent"
ohos:height="match_parent"
ohos:text="设备状态将显示在这里..."/>
</ScrollView>
</DirectionalLayout>
4. Ability配置 (config.json)
{
"abilities": [
{
"name": "MessageSenderAbility",
"type": "page",
"label": "MessageSender",
"icon": "$media:icon",
"launchType": "standard",
"backgroundModes": ["distributedNotification", "dataSync"]
}
]
}
四、与《鸿蒙跨端U同步》的技术关联
本项目借鉴了游戏多设备同步的以下关键技术:
- 状态同步机制:类似游戏中玩家状态的实时同步,本系统实现消息的实时同步
- 设备管理:参考游戏中的设备连接管理,实现设备上下线通知
- 冲突解决:采用类似游戏中的版本控制机制,确保消息顺序
- 数据格式:使用JSON作为跨设备数据交换格式,与游戏同步机制一致
增强的同步逻辑(借鉴游戏同步):
// 增强的消息广播方法,增加可靠性检查
private void broadcastMessage(Message message) {
// 检查设备连接状态
if (connectedDevices.isEmpty()) {
HiLog.warn(TAG, "No connected devices to broadcast");
return;
}
// 创建消息对象
JSONObject messageJson = new JSONObject();
try {
messageJson.put("content", message.getContent());
messageJson.put("timestamp", message.getTimestamp());
messageJson.put("senderId", message.getSenderId());
messageJson.put("senderName", message.getSenderName());
messageJson.put("version", getNextVersion());
// 增加消息类型标识
messageJson.put("type", "text_message");
// 增加重试机制
int retryCount = 0;
boolean success = false;
while (retryCount < 3 && !success) {
success = dataManager.putString(MESSAGE_CHANNEL,
messageJson.toString(),
DistributedDataManager.PUT_MODE_RELIABLE);
if (!success) {
retryCount++;
try {
Thread.sleep(200); // 短暂等待后重试
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}
if (!success) {
HiLog.error(TAG, "Failed to broadcast message after retries");
}
} catch (JSONException e) {
HiLog.error(TAG, "Failed to serialize message");
}
}
五、项目特色与创新点
- 实时消息同步:基于HarmonyOS分布式能力实现毫秒级消息同步
- 设备感知:实时显示所有连接设备状态
- 消息历史:完整记录所有设备发送的消息
- 可靠传输:借鉴游戏同步的重试机制,确保消息送达
- 轻量级设计:核心代码不超过300行,易于理解和扩展
六、总结
本项目成功实现了以下功能:
- 跨设备的实时文本消息发送与接收
- 设备连接状态的实时监控与显示
- 完整的消息历史记录
- 可靠的传输机制
通过借鉴游戏中的多设备同步技术,我们构建了一个稳定高效的跨设备通信系统。该系统不仅可以用于简单的消息传递,还可以扩展为:
- 跨设备文件共享
- 多设备协同办公
- 分布式计算任务分配
- 智能家居设备控制
未来可增加的功能包括:
- 消息加密传输
- 大文件分片传输
- 消息已读回执
- 设备间直接P2P通信
这个项目展示了HarmonyOS分布式能力的强大之处,为开发更复杂的跨设备应用奠定了基础。
更多推荐

所有评论(0)