HarmonyOS 超级终端与服务卡片开发:打造无缝多设备交互体验 #星光不负码向未来#
参与#星光不负码上未来#征文活动
欢迎继续探索 HarmonyOS 进阶系列 !在上篇《HarmonyOS 分布式与 AI 集成》中,我们实现了跨设备同步的智能备忘录应用。本篇将深入探讨 HarmonyOS 的超级终端(Super Device) 和 服务卡片(Service Widget) ,通过一个 跨设备协作的音乐播放器应用,展示如何利用超级终端实现设备间无缝连接,并通过服务卡片提供快捷交互入口,带来流畅的鸿蒙生态体验。
本文基于 HarmonyOS NEXT API 12+ ,使用 ArkTS 和 DevEco Studio 2025 ,结合 超级终端 API 和 服务卡片框架,实现音乐播放器的多设备协同和卡片化交互。让我们开始吧!
前置准备
| 工具 | 版本要求 | 下载链接 |
|---|---|---|
| DevEco Studio | 2025.1+ | 华为开发者官网 |
| JDK | 17 | 内置于 DevEco Studio |
| HarmonyOS 设备 | 手机/平板/手表/车机 | 华为 Mate 60 / MatePad / Watch 4 / AITO M9 |
| 模拟器 | API 12+ | DevEco Studio 内置 |
| HMS Core SDK | 6.13+ | 自动集成 |
项目结构:
music-player-app
├── entry/src/main/ets
│ ├── MainAbility
│ │ ├── pages
│ │ │ ├── Player.ets
│ │ │ └── Settings.ets
│ │ ├── services
│ │ │ └── MusicSyncService.ets
│ │ └── widgets
│ │ └── MusicWidget.ets
│ └── resources
│ └── base
│ └── media
│ └── icon.png
├── module.json5
└── build-profile.json5
安装环境:
- 安装 DevEco Studio:从 华为开发者官网 下载。
- 配置模拟器:Tools > Device Manager > Create Simulator(支持手机/平板/手表)。
- 验证:运行默认 "Hello World" 项目,确保模拟器或设备正常连接。
步骤 1:配置超级终端权限
在 module.json5 中添加超级终端和媒体相关权限:
json5
{
"module": {
"name": "entry",
"type": "entry",
"mainElement": "MainAbility",
"deviceTypes": [
"phone",
"tablet",
"wearable",
"car"
],
"requestPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DEVICE_STATE_CHANGE",
"reason": "$string:permission_device_state_reason",
"usedScene": {
"abilities": ["MainAbility"],
"when": "always"
}
},
{
"name": "ohos.permission.MEDIA_LOCATION",
"reason": "$string:permission_media_reason"
}
],
"metaData": {
"customizeData": [
{
"name": "Widget",
"value": "com.example.musicplayerapp.widgets.MusicWidget"
}
]
}
}
}
说明:
DISTRIBUTED_DEVICE_STATE_CHANGE:监听设备连接状态。MEDIA_LOCATION:访问音乐文件。metaData:注册服务卡片。
步骤 2:实现超级终端协同(分布式设备管理)
在 MusicSyncService.ets 中实现设备发现与音乐播放同步:
typescript
// entry/src/main/ets/MainAbility/services/MusicSyncService.ets
import deviceManager from '@ohos.distributedHardware.deviceManager'
import distributedData from '@ohos.data.distributedData'
import { BusinessError } from '@kit.BasicServicesKit'
class MusicSyncService {
private deviceManager: deviceManager.DeviceManager | null = null
private kvStore: distributedData.KVStore | null = null
private readonly STORE_ID = 'music_player_store'
async init(context: any): Promise<void> {
try {
// 初始化设备管理
this.deviceManager = await deviceManager.createDeviceManager(context.bundleName)
this.deviceManager.on('deviceStateChange', (data) => {
console.info(`Device ${data.deviceId} ${data.deviceState === 1 ? 'online' : 'offline'}`)
})
// 初始化分布式存储
const kvManager = distributedData.createKVManager({ context, bundleName: context.bundleName })
this.kvStore = await kvManager.getKVStore(this.STORE_ID, {
createIfMissing: true,
autoSync: true
})
} catch (error) {
console.error(`Init failed: ${(error as BusinessError).message}`)
}
}
async syncPlaybackState(state: PlaybackState): Promise<void> {
if (!this.kvStore) return
await this.kvStore.put('playback_state', JSON.stringify(state))
}
async getPlaybackState(): Promise<PlaybackState | null> {
if (!this.kvStore) return null
const state = await this.kvStore.get('playback_state')
return state ? JSON.parse(state) : null
}
async getAvailableDevices(): Promise<deviceManager.DeviceInfo[]> {
if (!this.deviceManager) return []
return await this.deviceManager.getTrustedDeviceList()
}
}
interface PlaybackState {
trackId: string
position: number
isPlaying: boolean
}
export const musicSyncService = new MusicSyncService()
亮点:
- 动态监听设备状态,实时更新可用设备列表。
- 使用 KVStore 同步播放状态(如曲目、进度、播放/暂停)。
步骤 3:实现音乐播放器 UI
在 Player.ets 中实现响应式播放器界面:
typescript
// entry/src/main/ets/MainAbility/pages/Player.ets
import media from '@ohos.multimedia.media'
import router from '@ohos.router'
@Entry
@Component
struct Player {
@State playbackState: PlaybackState = { trackId: 'track1', position: 0, isPlaying: false }
@State devices: deviceManager.DeviceInfo[] = []
private audioPlayer: media.AVPlayer | null = null
aboutToAppear() {
musicSyncService.init(this.context)
this.loadDevices()
this.initPlayer()
this.loadPlaybackState()
}
async loadDevices() {
this.devices = await musicSyncService.getAvailableDevices()
}
async loadPlaybackState() {
const state = await musicSyncService.getPlaybackState()
if (state) {
this.playbackState = state
}
}
async initPlayer() {
this.audioPlayer = await media.createAVPlayer()
this.audioPlayer.on('play', () => {
this.playbackState.isPlaying = true
musicSyncService.syncPlaybackState(this.playbackState)
})
this.audioPlayer.on('seekDone', (position) => {
this.playbackState.position = position
musicSyncService.syncPlaybackState(this.playbackState)
})
}
build() {
Column() {
Text(`Now Playing: ${this.playbackState.trackId}`)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin(10)
Progress(this.playbackState.position, 100)
.width('80%')
.margin(10)
Row() {
Button(this.playbackState.isPlaying ? 'Pause' : 'Play')
.fontSize(18)
.backgroundColor(this.playbackState.isPlaying ? '#F44336' : '#4CAF50')
.onClick(() => {
this.playbackState.isPlaying ? this.audioPlayer?.pause() : this.audioPlayer?.play()
})
Button('Settings')
.fontSize(18)
.backgroundColor('#2196F3')
.onClick(() => {
router.pushUrl({ url: 'pages/Settings' })
})
}
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
List() {
ForEach(this.devices, (device: deviceManager.DeviceInfo) => {
ListItem() {
Text(device.deviceName)
.fontSize(16)
}
})
}
.margin(10)
}
.width('100%')
.padding(20)
.backgroundColor('#F5F5F5')
}
}
说明:
- 使用
@ohos.multimedia.media播放音频。- 响应式 UI,支持手机、平板、车机等设备。

图源:华为开发者社区 - 音乐播放器 UI 示例
步骤 4:实现服务卡片
在 MusicWidget.ets 中实现桌面服务卡片:
typescript
// entry/src/main/ets/MainAbility/widgets/MusicWidget.ets
import formBindingData from '@ohos.app.form.formBindingData'
@Component
struct MusicWidget {
@State playbackState: PlaybackState = { trackId: 'track1', position: 0, isPlaying: false }
build() {
Column() {
Text(this.playbackState.trackId)
.fontSize(14)
.fontWeight(FontWeight.Medium)
Button(this.playbackState.isPlaying ? 'Pause' : 'Play')
.fontSize(12)
.width(80)
.height(30)
.onClick(() => {
this.playbackState.isPlaying = !this.playbackState.isPlaying
musicSyncService.syncPlaybackState(this.playbackState)
})
}
.width(160)
.height(100)
.backgroundColor('#FFFFFF')
}
}
export default {
onCreate() {
const formData = {
trackId: 'track1',
isPlaying: false
}
return formBindingData.createFormBindingData({ data: formData })
},
onUpdate(formId: string) {
// 更新卡片状态
},
onDestroy(formId: string) {
// 清理资源
}
}
说明:
- 服务卡片支持桌面快捷交互。
- 通过
formBindingData动态更新卡片内容。
步骤 5:构建与多设备调试
-
构建 HAP 包:
- Build > Build Hap > Generate Signed Hap。
- 输出
entry.hap和form.hap(服务卡片)。
-
多设备部署:
- 手机/平板:通过 DevEco Studio 直接安装。
- 手表/车机:使用远程调试(Tools > Remote Device)。
- 验证超级终端:确保设备通过华为账户绑定在同一局域网。
-
测试协同:
- 在手机上播放/暂停音乐,观察手表卡片和车机界面同步。
- 检查日志:Tools > Logcat,过滤 "MusicSyncService"。
进阶与最佳实践
-
性能优化:
-
缓存播放状态:
typescript@StorageLink('playbackCache') playbackState: PlaybackState
-
-
错误处理:
-
添加重试机制:
typescriptasync syncPlaybackState(state: PlaybackState, retries: number = 3): Promise<void> { for (let i = 0; i < retries; i++) { try { await this.kvStore.put('playback_state', JSON.stringify(state)) return } catch (error) { console.error(`Retry ${i + 1}: ${(error as BusinessError).message}`) } } }
-
-
卡片动态更新:
-
使用
FormProvider推送更新:typescriptimport FormProvider from '@ohos.app.form.FormProvider' FormProvider.updateForm(formId, formBindingData.createFormBindingData({ data }))
-
-
资源推荐:
- 华为开发者官网 - 超级终端
- Gitee - HarmonyOS 开源项目
- B站教程:"HarmonyOS 超级终端开发实战"
总结
通过本篇,你掌握了:
- 超级终端:实现手机、手表、车机间的音乐播放同步。
- 服务卡片:提供桌面快捷交互入口。
- 多设备适配:响应式 UI 适配不同设备。
下一期预告:《HarmonyOS 云服务与推送通知》------让你的应用随时与用户保持连接!
有问题?欢迎在评论区交流!喜欢请点赞分享~
(最后更新:2025 年 10 月 24 日)