1# 应用接入AVSession场景介绍 2 3音视频应用在实现音视频功能的同时,需要接入媒体会话即AVSession Kit,下文将提供一些典型的接入AVSession的展示和控制场景,方便开发者根据场景进行适配。 4 5对于不同的场景,将会在系统的播控中心看到不同的UI呈现。同时,在不同的场景下,应用的接入处理也需要遵循不同的规范约束。 6 7## 哪些场景下需要接入AVSession 8 9AVSession会对后台的音频播放、VOIP通话做约束,所以通常来说,长音频应用、听书类应用、长视频应用、VOIP类应用等都需要接入AVSession。当应用在没有创建接入AVSession的情况下进行了上述业务,那么系统会在检测到应用后台时,停止对应的音频播放,静音通话声音,以达到约束应用行为的目的。这种约束,应用上架前在本地就可以验证。 10 11对于其他使用到音频播放的应用,比如游戏,直播等场景,接入AVSession不是必选项,只是可选,取决于应用是否有后台播放的使用诉求。若应用需要后台播放,那么接入AVSession仍然是必须的,否则业务的正常功能会受到限制。 12 13当应用需要实现后台播放等功能时,需要使用[BackgroundTasks Kit](../../task-management/background-task-overview.md)(后台任务管理)的能力,申请对应的长时任务,避免进入挂起(Suspend)状态。 14 15## 接入流程 16 17应用接入AVSession流程分为如下几个步骤: 18 191. 确定应用需要创建的会话类型,[创建对应的会话](#创建不同类型的会话),不同类型决定了播控中心展示的控制模板样式。 202. 按需[创建后台任务](#创建后台任务)。 213. [设置必要的元数据(Metadata)](#设置元数据),以在播控中心展示响应的信息,包括不限于:当前媒体的ID(assetId),上一首媒体的ID(previousAssetId),下一首媒体的ID(nextAssetId),标题(title),专辑作者(author),专辑名称(album),词作者(writer),媒体时长(duration)等属性。 224. [设置播放相关的状态](#设置播放状态),包括不限于:当前媒体的播放状态(state)、播放位置(position)、播放倍速(speed)、缓冲时间(bufferedTime)、循环模式(loopMode)、是否收藏(isFavorite)、正在播放的媒体Id(activeItemId)、自定义媒体数据(extras)等属性。 235. 按需[注册不同的控制命令](#注册控制命令),包括不限于:播放/暂停、上下一首、快进快退、收藏、循环模式、进度条。 246. 应用退出或者无对应业务时,注销会话。 25 26## 创建不同类型的会话 27 28AVSession在构造方法中支持不同的类型参数,由 [AVSessionType](../../reference/apis-avsession-kit/js-apis-avsession.md#avsessiontype10) 定义,不同的类型代表了不同场景的控制能力,对于播控中心来说,会展示不同的控制模版。 29 30- audio类型,播控中心的控制样式为:收藏,上一首,播放/暂停,下一首,循环模式。 31 32- video类型,播控中心的控制样式为:快退,上一首,播放/暂停,下一首,快进。 33 34- voice_call类型,通话类型。 35 36使用代码示例: 37 38```ts 39import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 40 41// 开始创建并激活媒体会话 42// 创建session 43let context: Context = getContext(this); 44async function createSession() { 45 let type: AVSessionManager.AVSessionType = 'audio'; 46 let session = await AVSessionManager.createAVSession(context,'SESSION_NAME', type); 47 48 // 激活接口要在元数据、控制命令注册完成之后再执行 49 await session.activate(); 50 console.info(`session create done : sessionId : ${session.sessionId}`); 51} 52``` 53 54## 创建后台任务 55 56当应用需要实现后台播放等功能时,需要使用[BackgroundTasks Kit](../../task-management/background-task-overview.md)(后台任务管理)的能力,申请对应的长时任务,避免进入挂起(Suspend)状态。 57 58对媒体类播放来说,需要申请[AUDIO_PLAYBACK BackgroundMode](../../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-backgroundTaskManager.md#backgroundmode)的长时任务。 59 60 61## 设置元数据 62 63### 通用元数据 64 65应用可以通过setAVMetadata把会话的一些元数据信息设置给系统,从而在播控中心界面进行展示,包括不限制:当前媒体的ID(assetId),上一首媒体的ID(previousAssetId),下一首媒体的ID(nextAssetId),标题(title),专辑作者(author),专辑名称(album),词作者(writer),媒体时长(duration)等。 66 67```ts 68import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 69import { BusinessError } from '@kit.BasicServicesKit'; 70 71let context: Context = getContext(this); 72async function setSessionInfo() { 73 // 假设已经创建了一个session,如何创建session可以参考之前的案例 74 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', 'audio'); 75 // 设置必要的媒体信息 76 let metadata: AVSessionManager.AVMetadata = { 77 assetId: '0', // 由应用指定,用于标识应用媒体库里的媒体 78 title: 'TITLE', 79 mediaImage: 'IMAGE', 80 artist: 'ARTIST', 81 }; 82 session.setAVMetadata(metadata).then(() => { 83 console.info(`SetAVMetadata successfully`); 84 }).catch((err: BusinessError) => { 85 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 86 }); 87 } 88``` 89 90### 歌词 91 92对于长音频来说,播控中心提供了歌词的展示页面,对于应用来说,接入也比较简单,只需要把歌词内容设置给系统。播控中心会解析歌词内容,并根据播放进度进行同步的刷新。 93 94```ts 95import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 96import { BusinessError } from '@kit.BasicServicesKit'; 97 98let context: Context = getContext(this); 99async function setListener() { 100 // 假设已经创建了一个session,如何创建session可以参考之前的案例 101 let type: AVSessionManager.AVSessionType = 'audio'; 102 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 103 104 // 把歌词信息设置给AVSession 105 let metadata: AVSessionManager.AVMetadata = { 106 assetId: '0', 107 title: 'TITLE', 108 mediaImage: 'IMAGE', 109 // LRC中有两类元素:一种是时间标签+歌词,一种是ID标签。 110 // 例如:[00:25.44]xxx\r\n[00:26.44]xxx\r\n 111 lyric: "lrc格式歌词内容", 112 }; 113 session.setAVMetadata(metadata).then(() => { 114 console.info(`SetAVMetadata successfully`); 115 }).catch((err: BusinessError) => { 116 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 117 }); 118 119} 120``` 121 122<!--RP1--> 123<!--RP1End--> 124 125### 媒体资源金标 126 127对于长音频,播控中心提供了媒体资源金标的展示,媒体资源金标又可称为应用媒体音频音源的标识,目前暂时只支持展示AudioVivid标识。 128对于应用来说,接入只需要在AVMetadata中通知系统,当前播放音频的音源标识,播控就会同步展示。 129 130```ts 131import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 132import { BusinessError } from '@kit.BasicServicesKit'; 133 134let context: Context = getContext(this); 135async function setListener() { 136 // 假设已经创建了一个session,如何创建session可以参考之前的案例 137 let type: AVSessionManager.AVSessionType = 'audio'; 138 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 139 140 // 把媒体音源信息设置给AVSession 141 let metadata: AVSessionManager.AVMetadata = { 142 assetId: '0', 143 title: 'TITLE', 144 mediaImage: 'IMAGE', 145 // 标识该媒体音源是AudioVivid 146 displayTags: AVSessionManager.DisplayTag.TAG_AUDIO_VIVID, 147 }; 148 session.setAVMetadata(metadata).then(() => { 149 console.info(`SetAVMetadata successfully`); 150 }).catch((err: BusinessError) => { 151 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 152 }); 153} 154``` 155 156## 设置播放状态 157 158### 通用播放状态 159 160应用可以通过[setAVPlaybackState](../../reference/apis-avsession-kit/js-apis-avsession.md#setavplaybackstate10)。把当前的播放状态设置给系统,以在播控中心界面进行展示。 161播放状态一般是在资源播放后会进行变化的内容,包括:当前媒体的播放状态(state)、播放位置(position)、播放倍速(speed)、缓冲时间(bufferedTime)、循环模式(loopMode)、是否收藏(isFavorite)、正在播放的媒体Id(activeItemId)、自定义媒体数据(extras)等。 162 163```ts 164import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 165import { BusinessError } from '@kit.BasicServicesKit'; 166 167let context: Context = getContext(this); 168async function setSessionInfo() { 169 // 假设已经创建了一个session,如何创建session可以参考之前的案例 170 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', 'audio'); 171 172 // 播放器逻辑··· 引发媒体信息与播放状态的变更 173 // 简单设置一个播放状态 - 暂停 未收藏 174 let playbackState: AVSessionManager.AVPlaybackState = { 175 state:AVSessionManager.PlaybackState.PLAYBACK_STATE_PAUSE, 176 isFavorite:false 177 }; 178 session.setAVPlaybackState(playbackState, (err: BusinessError) => { 179 if (err) { 180 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 181 } else { 182 console.info(`SetAVPlaybackState successfully`); 183 } 184 }); 185} 186``` 187 188### 进度条 189 190应用如果支持在播控中心展示进度,那么在媒体资源播放中,需要设置资源的时长、播放状态(暂停、播放)、播放位置、倍速,播控中心会使用这些信息进行进度的展示: 191 192```ts 193import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 194import { BusinessError } from '@kit.BasicServicesKit'; 195 196let context: Context = getContext(this); 197async function setListener() { 198 // 假设已经创建了一个session,如何创建session可以参考之前的案例 199 let type: AVSessionManager.AVSessionType = 'audio'; 200 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 201 202 // 设置媒体资源时长 203 let metadata: AVSessionManager.AVMetadata = { 204 assetId: '0', 205 title: 'TITLE', 206 mediaImage: 'IMAGE', 207 duration: 23000, // 资源的时长,以ms为单位 208 }; 209 session.setAVMetadata(metadata).then(() => { 210 console.info(`SetAVMetadata successfully`); 211 }).catch((err: BusinessError) => { 212 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 213 }); 214 215 // 设置状态: 播放状态,进度位置,播放倍速,缓存的时间 216 let playbackState: AVSessionManager.AVPlaybackState = { 217 state: AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY, // 播放状态 218 position: { 219 elapsedTime: 1000, // 已经播放的位置,以ms为单位 220 updateTime: new Date().getTime(), // 应用更新当前位置时的时间戳,以ms为单位 221 }, 222 speed: 1.0, // 可选,默认是1.0,播放的倍速,按照应用内支持的speed进行设置,系统不做校验 223 bufferedTime: 14000, // 可选,资源缓存的时间,以ms为单位 224 }; 225 session.setAVPlaybackState(playbackState, (err) => { 226 if (err) { 227 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 228 } else { 229 console.info(`SetAVPlaybackState successfully`); 230 } 231 }); 232} 233``` 234 235系统的播控中心会根据应用设置的信息自行进行播放进度的计算,而不需要应用实时更新播放进度; 236但是应用需要如下状态发生变化的时候,再更新AVPlaybackState,否则系统会发生计算错误: 237 238- state 239- position 240- speed 241 242应用在真实播放开始时,再上报进度起始position;若播放存在buffer状态,可以先上报播放状态为AVSessionManager.PlaybackState.PLAYBACK_STATE_BUFFERING,来通知系统不刷新进度。 243 244关于进度条有一些特殊情况需要处理: 245 2461. 歌曲支持试听 247 248 (1)应用不需要设置完整的歌曲时长,则只需要设置歌曲的试听时长。当应用仅设置歌曲的试听时长而不是完整时长,用户在播控中心触发进度控制时,应用收到的时长也是VIP试听时长内的相对时间戳位置,而不是完整歌曲的绝对时间戳位置,应用需要重新计算歌曲从零开始的绝对时间戳进行实际响应处理。 249 250 (2)如果应用设置完整歌曲时长,但需要系统支持试听片段,也可以在播放时上报起始进度position,当收到的seek指令超过试听片段时,上报试听截止position,系统播控的进度会跟随回弹。 251 2522. 歌曲不支持试听 253 254 如果歌曲不支持试听,那么理论上应用内也不支持播放,这时可以把 duration 设置为 -1,以通知系统不显示实际的时长。 255 2563. 广告等内容的时长设置 257 258 对于有前贴广告、后贴广告的资源来说,建议这么处理: 259 - 播放广告时,单独设置广告的时长 duration。 260 - 当进入到正片播放的时候,则重新设置一次新的时长,以与广告进行区分。 261 262## 注册控制命令 263 264应用接入AVSession,可以通过注册不同的控制命令来实现播控中心界面上的控制操作,即通过on接口注册不同的控制命令参数,即可实现对应的功能。 265具体的接口参考[接口注册](../../reference/apis-avsession-kit/js-apis-avsession.md#onplay10)。 266> **说明:** 267> 268> 创建AVSession后,请先注册应用支持的控制命令,再激活 Session 269 270媒体资源支持的控制命令列表: 271 272| 控制命令 | 功能说明 | 273| ------ | -------------------------| 274| play | 播放命令。 | 275| pause | 暂停命令。 | 276| stop | 停止命令。 | 277| playNext | 播放下一首命令。 | 278| playPrevious | 播放上一首命令。 | 279| fastForward | 快进命令。 | 280| rewind | 快退命令。 | 281| playFromAssetId | 根据某个资源id进行播放命令。 | 282| seek | 跳转命令。 | 283| setSpeed | 设置播放速率命令。 | 284| setLoopMode | 设置循环模式命令。 | 285| toggleFavorite | 设置是否收藏命令。 | 286| skipToQueueItem | 设置播放列表其中某项被选中播放的命令。 | 287| handleKeyEvent | 设置按键事件的命令。 | 288| commonCommand | 设置自定义控制命令。 | 289 290通话类应用支持的控制: 291 292| 控制命令 | 功能说明 | 293| ------ | -------------------------| 294| answer | 接听电话的命令。 | 295| hangUp | 通话挂断的命令。 | 296| toggleCallMute | 通话静音或解除静音的命令。 | 297 298### 不支持命令的处理 299 300系统支持的控制命令对于不支持的控制,比如应用不支持“上一首”的命令处理,只需要使用off 接口注销对应的控制命令,系统的播控中心会相应的对该控制界面进行置灰处理,以明确告知用户此控制命令不支持。 301 302```ts 303import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 304 305let context: Context = getContext(this); 306async function unregisterSessionListener() { 307 // 假设已经创建了一个session,如何创建session可以参考之前的案例 308 let type: AVSessionManager.AVSessionType = 'audio'; 309 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 310 311 // 取消指定session下的相关监听 312 session.off('play'); 313 session.off('pause'); 314 session.off('stop'); 315 session.off('playNext'); 316 session.off('playPrevious'); 317} 318``` 319 320### 快进快退 321 322系统支持三种快进快退的时长,应用可以通过接口进行设置;同时注册快进快退的回调命令,以响应控制。 323 324```ts 325import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 326import { BusinessError } from '@kit.BasicServicesKit'; 327 328let context: Context = getContext(this); 329async function unregisterSessionListener() { 330 // 假设已经创建了一个session,如何创建session可以参考之前的案例 331 let type: AVSessionManager.AVSessionType = 'audio'; 332 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 333 334 // 设置支持的快进快退的时长设置给AVSession 335 let metadata: AVSessionManager.AVMetadata = { 336 assetId: '0', // 由应用指定,用于标识应用媒体库里的媒体 337 title: 'TITLE', 338 mediaImage: 'IMAGE', 339 skipIntervals: AVSessionManager.SkipIntervals.SECONDS_10, 340 }; 341 session.setAVMetadata(metadata).then(() => { 342 console.info(`SetAVMetadata successfully`); 343 }).catch((err: BusinessError) => { 344 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 345 }); 346 347 session.on('fastForward', (time ?: number) => { 348 console.info(`on fastForward , do fastForward task`); 349 // do some tasks ··· 350 }); 351 session.on('rewind', (time ?: number) => { 352 console.info(`on rewind , do rewind task`); 353 // do some tasks ··· 354 }); 355} 356``` 357 358### 收藏 359 360音乐类应用实现收藏功能,那么需要注册收藏的控制响应[on('toggleFavorite')](../../reference/apis-avsession-kit/js-apis-avsession.md#ontogglefavorite10)。 361 362```ts 363import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 364import { BusinessError } from '@kit.BasicServicesKit'; 365 366let context: Context = getContext(this); 367async function setListener() { 368 // 假设已经创建了一个session,如何创建session可以参考之前的案例 369 let type: AVSessionManager.AVSessionType = 'audio'; 370 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 371 session.on('toggleFavorite', (assetId) => { 372 console.info(`on toggleFavorite `); 373 // 应用收到收藏命令,进行收藏处理 374 375 // 应用内完成或者取消收藏,把新的收藏状态设置给AVSession 376 let playbackState: AVSessionManager.AVPlaybackState = { 377 isFavorite:true, 378 }; 379 session.setAVPlaybackState(playbackState).then(() => { 380 console.info(`SetAVPlaybackState successfully`); 381 }).catch((err: BusinessError) => { 382 console.info(`SetAVPlaybackState BusinessError: code: ${err.code}, message: ${err.message}`); 383 }); 384 385 }); 386} 387``` 388 389### 循环模式 390 391针对音乐类应用,系统的播控中心界面会默认展示循环模式的控制操作,目前系统支持四种固定的循环模式控制,参考: [LoopMode](../../reference/apis-avsession-kit/js-apis-avsession.md#loopmode10)。 392 393播控中心支持固定的四种循环模式的切换,即: 随机播放、顺序播放、单曲循环、列表循环。应用收到循环模式切换的指令并切换后,需要向系统上报切换后的LoopMode。 394若应用内支持的LoopMode不在系统固定的四个循环模式内,需要选择四个固定循环模式其一向系统上报,由应用自定。 395 396实现参考: 397 398```ts 399import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 400import { BusinessError } from '@kit.BasicServicesKit'; 401 402let context: Context = getContext(this); 403async function setListener() { 404 // 假设已经创建了一个session,如何创建session可以参考之前的案例 405 let type: AVSessionManager.AVSessionType = 'audio'; 406 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 407 408 // 应用启动时/内部切换循环模式,需要把应用内的当前的循环模式设置给AVSession 409 let playBackState: AVSessionManager.AVPlaybackState = { 410 loopMode: AVSessionManager.LoopMode.LOOP_MODE_SINGLE, 411 }; 412 session.setAVPlaybackState(playBackState).then(() => { 413 console.info(`set AVPlaybackState successfully`); 414 }).catch((err: BusinessError) => { 415 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 416 }); 417 418 // 应用注册循环模式的控制监听 419 session.on('setLoopMode', (mode) => { 420 console.info(`on setLoopMode ${mode}`); 421 // 应用收到设置循环模式的指令后,应用自定下一个模式,切换完毕后通过AVPlaybackState上报切换后的LoopMode 422 let playBackState: AVSessionManager.AVPlaybackState = { 423 loopMode: AVSessionManager.LoopMode.LOOP_MODE_SINGLE, 424 }; 425 session.setAVPlaybackState(playBackState).then(() => { 426 console.info(`set AVPlaybackState successfully`); 427 }).catch((err: BusinessError) => { 428 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 429 }); 430 }); 431 432} 433``` 434 435### 进度控制 436 437应用如果支持进度显示,进一步也可以支持进度控制。应用需要响应seek的控制命令,那么当用户在播控中心的界面上进行拖动操作时,应用就会收到对应的回调。参考实现: 438 439```ts 440import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 441 442let context: Context = getContext(this); 443async function setListener() { 444 // 假设已经创建了一个session,如何创建session可以参考之前的案例 445 let type: AVSessionManager.AVSessionType = 'audio'; 446 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 447 448 session.on('seek', (position: number) => { 449 console.info(`on seek , the time is ${JSON.stringify(position)}`); 450 451 // 由于应用内seek可能会触发较长的缓冲等待,可以先把状态设置为 Buffering 452 let playbackState: AVSessionManager.AVPlaybackState = { 453 state: AVSessionManager.PlaybackState.PLAYBACK_STATE_BUFFERING, // 缓冲状态 454 }; 455 session.setAVPlaybackState(playbackState, (err) => { 456 if (err) { 457 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 458 } else { 459 console.info(`SetAVPlaybackState successfully`); 460 } 461 }); 462 463 // 应用响应seek命令,使用应用内播放器完成seek实现 464 465 // 应用内更新新的位置后,也需要同步更新状态给系统 466 playbackState.state = AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY; // 播放状态 467 playbackState.position = { 468 elapsedTime: position, // 已经播放的位置,以ms为单位 469 updateTime: new Date().getTime(), // 应用更新当前位置的时间戳,以ms为单位 470 } 471 session.setAVPlaybackState(playbackState, (err) => { 472 if (err) { 473 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 474 } else { 475 console.info(`SetAVPlaybackState successfully`); 476 } 477 }); 478 479 }); 480} 481``` 482 483## 适配媒体通知 484 485当前系统不直接向应用提供主动发送媒体控制通知的接口,那么当应用正确接入媒体播控中心并进入播放状态时,系统会自动发送通知,同时在通知和锁屏界面进行展示。 486 487> **说明:** 488> 489> 通知中心、锁屏下的播控卡片的展示,由系统进行发送,并控制相应的生命周期。 490 491## 适配蓝牙按键与有线按键事件 492 493当前系统不直接向应用提供监听多模按键事件的接口,应用如需要监听蓝牙与有线耳机的媒体按键事件,可以通过注册AVSession的控制指令来实现。AVSession提供了如下两种实现方式: 494- 方式一(推荐使用): 495 按照应用业务需求,正确接入媒体播控中心,[注册需要的控制指令](#注册控制命令)并实现对应的功能。AVSession会监听多模按键事件,将其转换为AVSession的控制指令发送回应用。应用无须区分不同的按键事件,按照AVSession的回调处理即可。按照此方式接入播放暂停,也等同于适配了蓝牙耳机的佩戴检测,在双耳佩戴与摘下时也会收到如下播放暂停控制指令。目前支持转换的AVSession控制指令如下: 496 | 控制命令 | 功能说明 | 497 | ------ | -------------------------| 498 | play | 播放命令。 | 499 | pause | 暂停命令。 | 500 | stop | 停止命令。 | 501 | playNext | 播放下一首命令。 | 502 | playPrevious | 播放上一首命令。 | 503 | fastForward | 快进命令。 | 504 | rewind | 快退命令。 | 505 506 ```ts 507 import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 508 509 let context: Context = getContext(this); 510 async function setListenerForMesFromController() { 511 let type: AVSessionManager.AVSessionType = 'audio'; 512 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 513 // 设置必要的媒体信息,务必设置,否则接收不到控制事件 514 let metadata: AVSessionManager.AVMetadata = { 515 assetId: '0', // 由应用指定,用于标识应用媒体库里的媒体 516 title: 'TITLE', 517 mediaImage: 'IMAGE', 518 artist: 'ARTIST' 519 }; 520 session.setAVMetadata(metadata).then(() => { 521 console.info(`SetAVMetadata successfully`); 522 }).catch((err: BusinessError) => { 523 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 524 }); 525 // 一般在监听器中会对播放器做相应逻辑处理 526 // 不要忘记处理完后需要通过set接口同步播放相关信息,参考上面的用例 527 session.on('play', () => { 528 console.info(`on play , do play task`); 529 // 如暂不支持该指令,请勿注册;或在注册后但暂不使用时,通过session.off('play')取消监听 530 // 处理完毕后,请使用SetAVPlayState上报播放状态 531 }); 532 session.on('pause', () => { 533 console.info(`on pause , do pause task`); 534 // 如暂不支持该指令,请勿注册;或在注册后但暂不使用时,通过session.off('pause')取消监听 535 // 处理完毕后,请使用SetAVPlayState上报播放状态 536 }); 537 } 538 ``` 539 540- 方式二: 541 通过AVSession注册[HandleMediaKeyEvent](../../reference/apis-avsession-kit/js-apis-avsession.md#onhandlekeyevent10)指令。该回调接口会直接转发媒体按键事件[KeyEvent](../../reference/apis-input-kit/js-apis-keyevent.md)。应用需要自行识别按键事件的类型,并响应事件实现对应的功能。目前支持转发的按键事件类型如下: 542 | 按键类型([KeyCode](../../reference/apis-input-kit/js-apis-keycode.md#keycode)) | 功能说明 | 543 | ------ | -------------------------| 544 | KEYCODE_MEDIA_PLAY_PAUSE | 多媒体键:播放/暂停 | 545 | KEYCODE_MEDIA_STOP | 多媒体键:停止 | 546 | KEYCODE_MEDIA_NEXT | 多媒体键:下一首 | 547 | KEYCODE_MEDIA_PREVIOUS | 多媒体键:上一首 | 548 | KEYCODE_MEDIA_REWIND | 多媒体键:快退 | 549 | KEYCODE_MEDIA_FAST_FORWARD | 多媒体键:快进 | 550 | KEYCODE_MEDIA_PLAY | 多媒体键:播放 | 551 | KEYCODE_MEDIA_PAUSE | 多媒体键:暂停| 552 553 ```ts 554 import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 555 556 let context: Context = getContext(this); 557 async function setListenerForMesFromController() { 558 let type: AVSessionManager.AVSessionType = 'audio'; 559 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 560 // 设置必要的媒体信息,务必设置,否则接收不到按键事件 561 let metadata: AVSessionManager.AVMetadata = { 562 assetId: '0', // 由应用指定,用于标识应用媒体库里的媒体 563 title: 'TITLE', 564 mediaImage: 'IMAGE', 565 artist: 'ARTIST' 566 }; 567 session.setAVMetadata(metadata).then(() => { 568 console.info(`SetAVMetadata successfully`); 569 }).catch((err: BusinessError) => { 570 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 571 }); 572 session.on('handleKeyEvent', (event) => { 573 // 解析keycode,应用需要根据keycode对播放器做相应逻辑处理 574 console.info(`on handleKeyEvent, keyCode=${event.key.code}`); 575 }); 576 } 577 ``` 578 579> **说明:** 580> 581> 1. 方式一与方式二均需正确设置媒体信息AVMetadata并注册相应控制接口,否则会无法接收到控制指令与按键事件。 582> 2. 方式一与方式二,选择其一接入即可,无须同时接入,系统推荐按照方式一接入。 583 584<!--RP2--> 585<!--RP2End-->