鸿蒙APP开发:服务联邦跨服务无缝打通
鸿蒙系统中服务联邦跨服务无缝打通的技术实现,涵盖跨服务通信与数据同步机制,展示了如何在不同应用间实现服务联动与数据一致性。

鸿蒙系统中服务联邦跨服务无缝打通的技术实现,涵盖跨服务通信与数据同步机制,展示了如何在不同应用间实现服务联动与数据一致性。

这是《鸿蒙APP开发从入门到精通》的第8篇——服务联邦篇,承接第7篇的「超级终端多设备协同开发」,100%复用项目架构,为后续第9-12篇的电商购物车全栈项目铺垫服务联邦跨服务无缝打通的核心技术。
学习目标:
学习重点:
服务联邦跨服务无缝打通是HarmonyOS Next推出的一种全新应用形态,具有以下特点:
服务联邦跨服务无缝打通采用分布式架构,由以下部分组成:
基于第7篇的「MyFirstHarmonyApp」项目架构,实现以下功能:
在「entry/src/main/ets」目录下创建以下文件夹:
federated:存放服务联邦相关代码;ui:存放跨服务UI组件相关代码。entry/src/main/ets/utils/FederatedCommunicationManager.ets
import communication from '@ohos.federatedCommunication';
import { UIAbilityContext } from '@ohos.abilityAccessCtrl';
// 跨服务通信工具类
export class FederatedCommunicationManager {
private static instance: FederatedCommunicationManager | null = null;
private communicationHelper: communication.FederatedCommunicationHelper | null = null;
// 单例模式
static getInstance(): FederatedCommunicationManager {
if (!FederatedCommunicationManager.instance) {
FederatedCommunicationManager.instance = new FederatedCommunicationManager();
}
return FederatedCommunicationManager.instance;
}
// 初始化跨服务通信
async init(context: UIAbilityContext): Promise<void> {
if (!this.communicationHelper) {
this.communicationHelper = communication.createFederatedCommunicationHelper(context);
}
}
// 发现服务
onServiceFound(callback: (service: communication.FederatedServiceInfo) => void): void {
if (!this.communicationHelper) {
return;
}
this.communicationHelper.on('serviceFound', (service: communication.FederatedServiceInfo) => {
callback(service);
});
}
// 取消发现服务
offServiceFound(callback: (service: communication.FederatedServiceInfo) => void): void {
if (!this.communicationHelper) {
return;
}
this.communicationHelper.off('serviceFound', callback);
}
// 连接服务
async connectService(serviceId: string): Promise<boolean> {
if (!this.communicationHelper) {
return false;
}
const result = await this.communicationHelper.connect(serviceId);
return result === communication.ConnectResult.SUCCESS;
}
// 断开服务连接
async disconnectService(serviceId: string): Promise<boolean> {
if (!this.communicationHelper) {
return false;
}
const result = await this.communicationHelper.disconnect(serviceId);
return result === communication.DisconnectResult.SUCCESS;
}
// 发送消息
async sendMessage(serviceId: string, message: string): Promise<boolean> {
if (!this.communicationHelper) {
return false;
}
const result = await this.communicationHelper.sendMessage(serviceId, message);
return result === communication.SendResult.SUCCESS;
}
// 接收消息
onMessageReceived(callback: (serviceId: string, message: string) => void): void {
if (!this.communicationHelper) {
return;
}
this.communicationHelper.on('messageReceived', (serviceId: string, message: string) => {
callback(serviceId, message);
});
}
// 取消接收消息
offMessageReceived(callback: (serviceId: string, message: string) => void): void {
if (!this.communicationHelper) {
return;
}
this.communicationHelper.off('messageReceived', callback);
}
}
entry/src/main/ets/components/ServiceListComponent.ets
import { FederatedCommunicationManager } from '../utils/FederatedCommunicationManager';
import { communication } from '@ohos.federatedCommunication';
@Component
export struct ServiceListComponent {
@State serviceList: Array<communication.FederatedServiceInfo> = [];
@State connectedServiceId: string = '';
build() {
Column({ space: 16 }) {
Text('已连接服务')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.textColor('#000000');
List({ space: 16 }) {
ForEach(this.serviceList, (service: communication.FederatedServiceInfo) => {
ListItem() {
Row({ space: 16 }) {
Image(service.icon)
.width(40)
.height(40)
.objectFit(ImageFit.Contain);
Column({ space: 8 }) {
Text(service.name)
.fontSize(14)
.fontWeight(FontWeight.Bold)
.textColor('#000000');
Text(service.description)
.fontSize(14)
.textColor('#666666');
}.layoutWeight(1);
if (service.id === this.connectedServiceId) {
Text('已连接')
.fontSize(14)
.textColor('#007DFF');
} else {
Button('连接')
.width(80)
.height(40)
.backgroundColor('#007DFF')
.onClick(async () => {
const result = await FederatedCommunicationManager.getInstance().connectService(service.id);
if (result) {
this.connectedServiceId = service.id;
}
});
}
}
.width('100%')
.height('auto')
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(12);
}
.width('100%')
.height('auto');
}, (service: communication.FederatedServiceInfo) => service.id);
}
.width('100%')
.height('auto')
.padding(16);
Text('可连接服务')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.textColor('#000000');
List({ space: 16 }) {
// 可连接服务列表
}
.width('100%')
.height('auto')
.padding(16);
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5');
}
aboutToAppear() {
// 监听服务发现
FederatedCommunicationManager.getInstance().onServiceFound((service: communication.FederatedServiceInfo) => {
this.serviceList.push(service);
});
}
}
entry/src/main/ets/utils/FederatedDataManager.ets
import dataShare from '@ohos.data.dataShare';
import { UIAbilityContext } from '@ohos.abilityAccessCtrl';
// 跨服务数据同步工具类
export class FederatedDataManager {
private static instance: FederatedDataManager | null = null;
private dataShareHelper: dataShare.DataShareHelper | null = null;
// 单例模式
static getInstance(): FederatedDataManager {
if (!FederatedDataManager.instance) {
FederatedDataManager.instance = new FederatedDataManager();
}
return FederatedDataManager.instance;
}
// 初始化跨服务数据同步
async init(context: UIAbilityContext): Promise<void> {
if (!this.dataShareHelper) {
const uri = 'dataability://com.example.myapp';
this.dataShareHelper = await dataShare.createDataShareHelper(context, uri);
}
}
// 保存数据
async saveData(key: string, value: any): Promise<void> {
if (!this.dataShareHelper) {
return;
}
await this.dataShareHelper.insert('data', { key, value });
}
// 获取数据
async getData(key: string): Promise<any> {
if (!this.dataShareHelper) {
return null;
}
const result = await this.dataShareHelper.query('data', { key });
if (result && result.length > 0) {
return result[0].value;
}
return null;
}
// 删除数据
async deleteData(key: string): Promise<void> {
if (!this.dataShareHelper) {
return;
}
await this.dataShareHelper.delete('data', { key });
}
// 监听数据变化
onDataChange(key: string, callback: (value: any) => void): void {
if (!this.dataShareHelper) {
return;
}
this.dataShareHelper.on('dataChange', (data: any) => {
if (data.key === key) {
callback(data.value);
}
});
}
// 取消监听数据变化
offDataChange(key: string, callback: (value: any) => void): void {
if (!this.dataShareHelper) {
return;
}
this.dataShareHelper.off('dataChange', callback);
}
}
entry/src/main/ets/services/SearchService.ets(修改)
import { FederatedDataManager } from '../utils/FederatedDataManager';
// 搜索服务
export class SearchService {
// ...
// 保存搜索记录
async saveSearchHistory(keyword: string): Promise<void> {
const history = await this.getSearchHistory();
const index = history.findIndex(item => item === keyword);
if (index !== -1) {
history.splice(index, 1);
}
history.unshift(keyword);
if (history.length > 10) {
history.splice(10);
}
await FederatedDataManager.getInstance().saveData('searchHistory', history);
}
// 获取搜索记录
async getSearchHistory(): Promise<Array<string>> {
const history = await FederatedDataManager.getInstance().getData('searchHistory');
return history || [];
}
// 删除搜索记录
async deleteSearchHistory(keyword: string): Promise<void> {
const history = await this.getSearchHistory();
const index = history.findIndex(item => item === keyword);
if (index !== -1) {
history.splice(index, 1);
await FederatedDataManager.getInstance().saveData('searchHistory', history);
}
}
// 清空搜索记录
async clearSearchHistory(): Promise<void> {
await FederatedDataManager.getInstance().deleteData('searchHistory');
}
}
entry/src/main/ets/services/CartService.ets(修改)
import { FederatedDataManager } from '../utils/FederatedDataManager';
// 购物车服务
export class CartService {
// ...
// 添加商品到购物车
async addToCart(productId: number, count: number): Promise<void> {
const cartItems = await this.getCartItems();
const index = cartItems.findIndex(item => item.productId === productId);
if (index !== -1) {
cartItems[index].count += count;
} else {
const product = goodsData.find(item => item.id === productId);
if (product) {
cartItems.push({ id: productId, productId, name: product.name, imageUrl: product.imageUrl, price: product.price, count, isChecked: false });
}
}
await this.saveCartItems(cartItems);
// 同步到跨服务数据管理
await FederatedDataManager.getInstance().saveData('cartItems', cartItems);
}
// 获取购物车商品
async getCartItems(): Promise<Array<CartItemModel>> {
// 先从跨服务数据管理获取
const remoteData = await FederatedDataManager.getInstance().getData('cartItems');
if (remoteData) {
return remoteData;
}
// 跨服务数据管理无数据,从本地数据库获取
const localData = await this.getCartItemsFromLocal();
return localData;
}
// 删除购物车商品
async deleteCartItem(id: number): Promise<void> {
const cartItems = await this.getCartItems();
const index = cartItems.findIndex(item => item.id === id);
if (index !== -1) {
cartItems.splice(index, 1);
await this.saveCartItems(cartItems);
// 同步到跨服务数据管理
await FederatedDataManager.getInstance().saveData('cartItems', cartItems);
}
}
// 清空购物车
async clearCart(): Promise<void> {
await this.saveCartItems([]);
// 同步到跨服务数据管理
await FederatedDataManager.getInstance().saveData('cartItems', []);
}
}
在「entry/src/main/module.json5」中添加服务联邦配置:
{
"module": {
"requestPermissions": [
{ "name": "ohos.permission.DISTRIBUTED_DATASYNC" },
{ "name": "ohos.permission.DISTRIBUTED_COMMUNICATION" },
{ "name": "ohos.permission.GET_NETWORK_INFO" },
{ "name": "ohos.permission.READ_EXTERNAL_STORAGE" },
{ "name": "ohos.permission.WRITE_EXTERNAL_STORAGE" }
],
"abilities": [],
"widgets": [],
"pages": []
}
}
✅ 跨服务无缝打通:在其他应用中搜索商品,在MyFirstHarmonyApp中查看商品详情;
✅ 数据同步:购物车数据在不同应用间同步;
✅ 服务发现:自动发现附近的鸿蒙应用服务;
✅ 服务连接:手动连接附近的鸿蒙应用服务。
本文完成了:

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online