1# Accessing AVSession 2<!--Kit: AVSession Kit--> 3<!--Subsystem: Multimedia--> 4<!--Owner: @ccfriend; @liao_qian--> 5<!--SE: @ccfriend--> 6<!--TSE: @chenmingxi1_huawei--> 7 8In addition to the implementation of audio and video playback, media applications may need to access AVSession provided by AVSession Kit for display and control purposes. This topic describes typical display and control scenarios of accessing AVSession. 9 10In different access scenarios, different UIs are displayed in the controller of the system, and different specifications are posed for application access processing. 11 12## Scenarios That Require AVSession Access 13 14AVSession restricts background audio playback and VoIP calls. As such, applications that provide long-duration audio or video playback, audiobook applications, and VoIP applications need to access AVSession. If such an application does not access AVSession, the system stops its audio playback or mutes the ongoing call when detecting that the application is running in the background. In this way, the application behavior is restricted. You can verify the restriction locally before the application is released. 15 16For applications that may use audio playback, such as gaming and live broadcast applications, accessing AVSession is optional. However, if they want to continue audio playback after switching to the background, they must access AVSession. 17 18To implement background playback, the application must also use [Background Tasks Kit](../../task-management/background-task-overview.md) to request a continuous task to avoid being suspended. 19 20## Access Process 21 22The process for implementing AVSession access is as follows: 23 241. Determine the type of AVSession to be created for the application, and then [create one](#creating-avsession). The AVSession type determines the style of the control template displayed in the controller. 252. [Create a background task](#creating-a-background-task). 263. [Set necessary metadata](#setting-metadata), which is the response information displayed in the controller. The metadata includes the IDs of the current media asset (assetId), previous media asset (previousAssetId), and next media asset (nextAssetId), title, author, album, writer, and duration. 274. [Set playback state information](#setting-playback-state-information). The information includes the playback state, position, speed, buffered time, loop mode, media item being played (activeItemId), custom media data (extras), and whether the media asset is favorited (isFavorite). 285. [Register control commands](#registering-control-commands). The control commands include **play**, **pause**, **previous**, **next**, **fastForward**, **rewind**, **toggleFavorite**, **setLoopMode**, and **seek**. 296. Destroy AVSession when the application exits or stops providing service. 30 31## Creating AVSession 32 33[AVSessionType](../../reference/apis-avsession-kit/arkts-apis-avsession-t.md#avsessiontype10) in the constructor determines the type of AVSession to create. Different AVSession types represent the control capabilities in various scenarios and display different control templates in the controller. 34 35- For audio AVSession, the controller provides the following control buttons: favorite, previous, play/pause, next, and loop mode. 36 37- For video AVSession, the controller provides the following control buttons: rewind, previous, play/pause, next, and fast-forward. 38 39- For voice_call AVSession, the application is not displayed in the controller. 40 41Refer to the code snippet below: 42 43> **NOTE** 44> 45> The sample code below demonstrates only the API call for creating an AVSession object. When actually using it, the application must ensure that the AVSession object remains throughout the application's background playback activities. This prevents the system from reclaiming or releasing it, which could lead to playback being controlled by the system. 46 47```ts 48import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 49 50@Entry 51@Component 52struct Index { 53 @State message: string = 'hello world'; 54 55 build() { 56 Column() { 57 Text(this.message) 58 .onClick(async () => { 59 // Start to create and activate an AVSession object. 60 // Create an AVSession object. 61 let context = this.getUIContext().getHostContext() as Context; 62 let type: AVSessionManager.AVSessionType = 'audio'; 63 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 64 // Call activate() after the metadata and control commands are registered. 65 await session.activate(); 66 console.info(`session create done : sessionId : ${session.sessionId}`); 67 }) 68 } 69 .width('100%') 70 .height('100%') 71 } 72} 73``` 74 75## Creating a Background Task 76 77To implement background playback, the application must also use [Background Tasks Kit](../../task-management/background-task-overview.md) to request a continuous task to avoid being suspended. 78 79Media playback applications must request a continuous task of the [AUDIO_PLAYBACK](../../reference/apis-backgroundtasks-kit/js-apis-resourceschedule-backgroundTaskManager.md#backgroundmode) background mode. 80 81 82## Setting Metadata 83 84### Setting Common Metadata 85 86The application can call **setAVMetadata()** to set AVSession metadata to the system so that the metadata can be displayed in the controller. The metadata includes the IDs of the current media asset (assetId), previous media asset (previousAssetId), and next media asset (nextAssetId), title, author, album, writer, and duration. 87 88```ts 89import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 90import { BusinessError } from '@kit.BasicServicesKit'; 91 92@Entry 93@Component 94struct Index { 95 @State message: string = 'hello world'; 96 97 build() { 98 Column() { 99 Text(this.message) 100 .onClick(async () => { 101 let context = this.getUIContext().getHostContext() as Context; 102 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet above. 103 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', 'audio'); 104 // Set necessary AVSession metadata. 105 let metadata: AVSessionManager.AVMetadata = { 106 assetId: '0', // Specified by the application, used to identify the media asset in the application media library. 107 title: 'TITLE', 108 mediaImage: 'IMAGE', 109 artist: 'ARTIST', 110 }; 111 session.setAVMetadata(metadata).then(() => { 112 console.info(`SetAVMetadata successfully`); 113 }).catch((err: BusinessError) => { 114 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 115 }); 116 }) 117 } 118 .width('100%') 119 .height('100%') 120 } 121} 122``` 123 124### Setting Lyrics 125 126The controller provides the UI to show lyrics. The application only needs to set the lyrics content. The controller parses the lyrics content and displays it based on the playback progress. 127 128```ts 129import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 130import { BusinessError } from '@kit.BasicServicesKit'; 131 132@Entry 133@Component 134struct Index { 135 @State message: string = 'hello world'; 136 137 build() { 138 Column() { 139 Text(this.message) 140 .onClick(async () => { 141 let context = this.getUIContext().getHostContext() as Context; 142 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet above. 143 let type: AVSessionManager.AVSessionType = 'audio'; 144 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 145 146 // Set the lyric to AVSession. 147 let metadata: AVSessionManager.AVMetadata = { 148 assetId: '0', 149 title: 'TITLE', 150 mediaImage: 'IMAGE', 151 // The LRC contains two types of elements: time tag + lyrics, and ID tag. 152 // Example: [00:25.44]xxx\r\n[00:26.44]xxx\r\n 153 lyric: "Lyrics in LRC format", 154 // The singleLyricText field stores a single line of lyric text without timestamps. 155 // Example: "Content of a single lyric line" 156 singleLyricText: "Content of a single lyric line", 157 }; 158 session.setAVMetadata(metadata).then(() => { 159 console.info(`SetAVMetadata successfully`); 160 }).catch((err: BusinessError) => { 161 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 162 }); 163 }) 164 } 165 .width('100%') 166 .height('100%') 167 } 168} 169``` 170 171<!--RP1--> 172<!--RP1End--> 173 174### Display Tags of Media Assets 175 176The controller displays a special type identifier for long-duration media assets. Currently, only the Audio Vivid identifier is displayed. 177 178The application notifies the system of the display tag of the media asset through the AVMetadata during the access, and the controller displays the tag when the media asset is being played. 179 180```ts 181import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 182import { BusinessError } from '@kit.BasicServicesKit'; 183 184@Entry 185@Component 186struct Index { 187 @State message: string = 'hello world'; 188 189 build() { 190 Column() { 191 Text(this.message) 192 .onClick(async () => { 193 let context = this.getUIContext().getHostContext() as Context; 194 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet above. 195 let type: AVSessionManager.AVSessionType = 'audio'; 196 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 197 198 // Set the media audio source information to AVSession. 199 let metadata: AVSessionManager.AVMetadata = { 200 assetId: '0', 201 title: 'TITLE', 202 mediaImage: 'IMAGE', 203 // The display tag of the audio source is Audio Vivid. 204 displayTags: AVSessionManager.DisplayTag.TAG_AUDIO_VIVID, 205 }; 206 session.setAVMetadata(metadata).then(() => { 207 console.info(`SetAVMetadata successfully`); 208 }).catch((err: BusinessError) => { 209 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 210 }); 211 }) 212 } 213 .width('100%') 214 .height('100%') 215 } 216} 217``` 218 219## Setting Playback State Information 220 221### Setting General State Information 222 223The application can call [setAVPlaybackState](../../reference/apis-avsession-kit/arkts-apis-avsession-AVSession.md#setavplaybackstate10) to set the playback state information to the system so that the information can be displayed in the controller. 224 225Generally, the playback state information includes the playback state, position, speed, buffered time, loop mode, media item being played (activeItemId), custom media data (extras), and whether the media asset is favorited (isFavorite). It changes during the playback. 226 227```ts 228import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 229import { BusinessError } from '@kit.BasicServicesKit'; 230 231@Entry 232@Component 233struct Index { 234 @State message: string = 'hello world'; 235 236 build() { 237 Column() { 238 Text(this.message) 239 .onClick(async () => { 240 let context = this.getUIContext().getHostContext() as Context; 241 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet above. 242 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', 'audio'); 243 244 // The player logic that triggers changes in the session metadata and playback state is omitted here. 245 // Set the playback state to paused and set isFavorite to false. 246 let playbackState: AVSessionManager.AVPlaybackState = { 247 state: AVSessionManager.PlaybackState.PLAYBACK_STATE_PAUSE, 248 isFavorite: false 249 }; 250 session.setAVPlaybackState(playbackState, (err: BusinessError) => { 251 if (err) { 252 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 253 } else { 254 console.info(`SetAVPlaybackState successfully`); 255 } 256 }); 257 }) 258 } 259 .width('100%') 260 .height('100%') 261 } 262} 263``` 264 265### Setting the Progress Bar 266 267To display a progress bar in the controller, the application must set the duration, playback state (pause or play), playback position, and playback speed. The controller displays the progress bar based on the information. 268 269```ts 270import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 271import { BusinessError } from '@kit.BasicServicesKit'; 272 273@Entry 274@Component 275struct Index { 276 @State message: string = 'hello world'; 277 278 build() { 279 Column() { 280 Text(this.message) 281 .onClick(async () => { 282 let context = this.getUIContext().getHostContext() as Context; 283 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet above. 284 let type: AVSessionManager.AVSessionType = 'audio'; 285 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 286 287 // Set the media resource duration. 288 let metadata: AVSessionManager.AVMetadata = { 289 assetId: '0', 290 title: 'TITLE', 291 mediaImage: 'IMAGE', 292 duration: 23000, // Duration of the media asset, in milliseconds. 293 }; 294 session.setAVMetadata(metadata).then(() => { 295 console.info(`SetAVMetadata successfully`); 296 }).catch((err: BusinessError) => { 297 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 298 }); 299 300 // Set the playback state information, including the playback state, position, speed, and buffered time. 301 let playbackState: AVSessionManager.AVPlaybackState = { 302 state: AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY, // Playing state. 303 position: { 304 elapsedTime: 1000, // Playback position, in milliseconds. 305 updateTime: new Date().getTime(), // Timestamp when the application updates the current position, in milliseconds. 306 }, 307 speed: 1.0, // Optional. The default value is 1.0. The playback speed is set based on the speed supported by the application. The system does not verify the speed. 308 bufferedTime: 14000, // Optional. Buffered time, in milliseconds. 309 }; 310 session.setAVPlaybackState(playbackState, (err) => { 311 if (err) { 312 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 313 } else { 314 console.info(`SetAVPlaybackState successfully`); 315 } 316 }); 317 }) 318 } 319 .width('100%') 320 .height('100%') 321 } 322} 323``` 324 325The controller calculates the playback progress based on the information set by the application. The application does not need to update the playback progress in real time. 326 327However, it needs to update the playback state when the following information changes to avid calculation errors: 328 329- state 330- position 331- speed 332 333The application reports the start position of the progress once the actual playback starts. If the playback is in the buffer state, the application can report **AVSessionManager.PlaybackState.PLAYBACK_STATE_BUFFERING** to instruct the system not to update the progress. 334 335Certain special processing is required when setting the progress bar. 336 3371. Songs that can be previewed 338 339 (1) The application sets the preview duration, rather than the total duration, for a song. In this case, when the user performs progress control in the controller, the application receives the relative timestamp within the preview duration, rather than that within the total duration. The application needs to calculate the absolute timestamp from the very beginning of the song. 340 341 (2) The application sets the total duration for a song but requires the system to provide preview, the application can report the start position of the progress when the playback starts, and report the end position when the received seek instruction is not within the preview duration. In the latter case, the playback control progress of the system rebounds. 342 3432. Songs that do not support preview 344 345 If a song cannot be previewed, it cannot be displayed by the application. In this case, the application should set the duration to **-1**, so the system does not display the actual duration. 346 3473. Special contents such as ads 348 349 For media assets with pre-roll or post-roll ads, you are advised to: 350 - Set the ad duration separately. 351 - Set a new duration for the actual content, to distinguish it from the ad. 352 353## Registering Control Commands 354 355The application can register different control commands through **on()** to implement control operations in the controller. For details, see the [API reference](../../reference/apis-avsession-kit/arkts-apis-avsession-AVSession.md#onplay10). 356> **NOTE** 357> 358> After an AVSession object is created, register control commands supported by the application before activating the object. 359 360The table below lists the control commands supported by media assets. 361 362| Control Command| Description | 363| ------ | -------------------------| 364| play | Plays the media.| 365| pause | Pauses the playback.| 366| stop | Stops the playback.| 367| playNext | Plays the next media asset.| 368| playPrevious | Plays the previous media asset.| 369| fastForward | Fast-forwards.| 370| rewind | Rewinds.| 371| playFromAssetId | Plays a media asset with a given asset ID.| 372| seek | Seeks to a playback position. | 373| setSpeed | Sets the playback speed.| 374| setLoopMode | Sets the loop mode.| 375| toggleFavorite | Favorites or unfavorites a media asset.| 376| skipToQueueItem | Selects an item in the playlist.| 377| handleKeyEvent | Sets a key event.| 378| commonCommand | Customizes a control command.| 379 380The table below lists the control commands for calling applications. 381 382| Control Command| Description | 383| ------ | -------------------------| 384| answer | Answers a call.| 385| hangUp | Ends a call.| 386| toggleCallMute | Mutes or unmutes a call.| 387 388### Handling Unsupported Commands 389 390If the application does not support a control command supported by the system, for example, the **playPrevious** command, it can use **off()** to deregister the control command. Then the controller grays out the control page accordingly, so that users know that the control command is not supported. 391 392```ts 393import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 394 395@Entry 396@Component 397struct Index { 398 @State message: string = 'hello world'; 399 400 build() { 401 Column() { 402 Text(this.message) 403 .onClick(async () => { 404 let context = this.getUIContext().getHostContext() as Context; 405 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet above. 406 let type: AVSessionManager.AVSessionType = 'audio'; 407 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 408 409 // Cancel the listener of the AVSession object. 410 session.off('play'); 411 session.off('pause'); 412 session.off('stop'); 413 session.off('playNext'); 414 session.off('playPrevious'); 415 }) 416 } 417 .width('100%') 418 .height('100%') 419 } 420} 421``` 422 423### Setting Fast-Forward or Rewind 424 425The application can call APIs to set the fast-forward or rewind intervals in three different ways. It also registers the fast-forward or rewind control command to respond to user operations. 426 427```ts 428import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 429import { BusinessError } from '@kit.BasicServicesKit'; 430 431@Entry 432@Component 433struct Index { 434 @State message: string = 'hello world'; 435 436 build() { 437 Column() { 438 Text(this.message) 439 .onClick(async () => { 440 let context = this.getUIContext().getHostContext() as Context; 441 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet above. 442 let type: AVSessionManager.AVSessionType = 'audio'; 443 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 444 445 // Set the supported fast-forward or rewind duration for AVSession. 446 let metadata: AVSessionManager.AVMetadata = { 447 assetId: '0', // Specified by the application, used to identify the media asset in the application media library. 448 title: 'TITLE', 449 mediaImage: 'IMAGE', 450 skipIntervals: AVSessionManager.SkipIntervals.SECONDS_10, 451 }; 452 session.setAVMetadata(metadata).then(() => { 453 console.info(`SetAVMetadata successfully`); 454 }).catch((err: BusinessError) => { 455 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 456 }); 457 458 session.on('fastForward', (time ?: number) => { 459 console.info(`on fastForward , do fastForward task`); 460 // do some tasks ··· 461 }); 462 session.on('rewind', (time ?: number) => { 463 console.info(`on rewind , do rewind task`); 464 // do some tasks ··· 465 }); 466 }) 467 } 468 .width('100%') 469 .height('100%') 470 } 471} 472``` 473 474### Favoriting Media Assets 475 476To implement favoriting, a music application must call [on('toggleFavorite')](../../reference/apis-avsession-kit/arkts-apis-avsession-AVSession.md#ontogglefavorite10) to register the **toggleFavorite** control command. 477 478```ts 479import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 480import { BusinessError } from '@kit.BasicServicesKit'; 481 482@Entry 483@Component 484struct Index { 485 @State message: string = 'hello world'; 486 487 build() { 488 Column() { 489 Text(this.message) 490 .onClick(async () => { 491 let context = this.getUIContext().getHostContext() as Context; 492 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet above. 493 let type: AVSessionManager.AVSessionType = 'audio'; 494 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 495 session.on('toggleFavorite', (assetId) => { 496 console.info(`on toggleFavorite `); 497 // The application receives the toggleFavorite command and favorites or unfavorites the media asset. 498 499 // Set the new state to AVSession after the application finishes favoriting or unfavoriting. 500 let playbackState: AVSessionManager.AVPlaybackState = { 501 isFavorite: true, 502 }; 503 session.setAVPlaybackState(playbackState).then(() => { 504 console.info(`SetAVPlaybackState successfully`); 505 }).catch((err: BusinessError) => { 506 console.error(`SetAVPlaybackState BusinessError: code: ${err.code}, message: ${err.message}`); 507 }); 508 }); 509 }) 510 } 511 .width('100%') 512 .height('100%') 513 } 514} 515``` 516 517### Setting the Loop Mode 518 519For music applications, the controller displays control operations in loop mode by default. Currently, the system supports four fixed [loop modes](../../reference/apis-avsession-kit/arkts-apis-avsession-e.md#loopmode10), namely, shuffle, sequential playback, single loop, and playlist loop. After switching the loop mode as instructed, the application needs to report the new loop mode. 520 521Even if the application does not support the four fixed loop modes, it must report one of them to the system. 522 523Refer to the code snippet below: 524 525```ts 526import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 527import { BusinessError } from '@kit.BasicServicesKit'; 528 529@Entry 530@Component 531struct Index { 532 @State message: string = 'hello world'; 533 534 build() { 535 Column() { 536 Text(this.message) 537 .onClick(async () => { 538 let context = this.getUIContext().getHostContext() as Context; 539 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet above. 540 let type: AVSessionManager.AVSessionType = 'audio'; 541 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 542 543 // When the application starts or switches the loop mode, it sets the loop mode in use to the AVSession. 544 let playBackState: AVSessionManager.AVPlaybackState = { 545 loopMode: AVSessionManager.LoopMode.LOOP_MODE_SINGLE, 546 }; 547 session.setAVPlaybackState(playBackState).then(() => { 548 console.info(`set AVPlaybackState successfully`); 549 }).catch((err: BusinessError) => { 550 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 551 }); 552 553 // The application listens for loop mode changes. 554 session.on('setLoopMode', (mode) => { 555 console.info(`on setLoopMode ${mode}`); 556 // After receiving the instruction for setting the loop mode, the application determines the next mode. After the switching is complete, the application reports the new loop mode through AVPlaybackState. 557 let playBackState: AVSessionManager.AVPlaybackState = { 558 loopMode: AVSessionManager.LoopMode.LOOP_MODE_SINGLE, 559 }; 560 session.setAVPlaybackState(playBackState).then(() => { 561 console.info(`set AVPlaybackState successfully`); 562 }).catch((err: BusinessError) => { 563 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 564 }); 565 }); 566 }) 567 } 568 .width('100%') 569 .height('100%') 570 } 571} 572``` 573 574### Performing Progress Control 575 576An application that supports progress display can further supports progress control. To support progress control, the application must respond to the **seek** control command. When users drag the progress bar in the controller, the application receives a callback. Refer to the code snippet below: 577 578```ts 579import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 580 581@Entry 582@Component 583struct Index { 584 @State message: string = 'hello world'; 585 586 build() { 587 Column() { 588 Text(this.message) 589 .onClick(async () => { 590 let context = this.getUIContext().getHostContext() as Context; 591 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet above. 592 let type: AVSessionManager.AVSessionType = 'audio'; 593 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 594 595 session.on('seek', (position: number) => { 596 console.info(`on seek , the time is ${JSON.stringify(position)}`); 597 598 // The seek operation may trigger a long buffering time. You can set the playback state to PLAYBACK_STATE_BUFFERING. 599 let playbackState: AVSessionManager.AVPlaybackState = { 600 state: AVSessionManager.PlaybackState.PLAYBACK_STATE_BUFFERING, // Buffering state. 601 }; 602 session.setAVPlaybackState(playbackState, (err) => { 603 if (err) { 604 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 605 } else { 606 console.info(`SetAVPlaybackState successfully`); 607 } 608 }); 609 610 // The application responds to the seek command and seeks to the specified position. 611 612 // After seeking to the specified position, the application synchronizes the new position to the system. 613 playbackState.state = AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY; // Playing state. 614 playbackState.position = { 615 elapsedTime: position, // Playback position, in milliseconds. 616 updateTime: new Date().getTime(), // Timestamp when the application updates the current position, in milliseconds. 617 } 618 session.setAVPlaybackState(playbackState, (err) => { 619 if (err) { 620 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 621 } else { 622 console.info(`SetAVPlaybackState successfully`); 623 } 624 }); 625 }); 626 }) 627 } 628 .width('100%') 629 .height('100%') 630 } 631} 632``` 633 634## Adapting to Media Notification 635 636Currently, the system does not provide APIs for proactively sending control notifications to applications. When an application that has integrated the media controller enters the playing state, the system automatically sends a notification and displays the notification in the notification center and on the lock screen. 637 638> **NOTE** 639> 640> The system sends playback control widgets in the notification center and on the lock screen and controls their lifecycle. 641 642## Adapting to Bluetooth and Wired Key Events 643 644Currently, the system does not provide APIs for listening for multimodal key events for applications. If an application needs to listen for media key events from Bluetooth and wired headsets, the application can register control commands with AVSession. AVSession provides the following two methods for implementation: 645- Method 1 (recommended) 646 647 Integrate the media controller based on service requirements, [register the required control commands](#registering-control-commands), and implement the corresponding functionalities. AVSession listens for multimodal key events, converts them into AVSession control commands, and sends them to the application. The application does not need to differentiate between various key events. Instead, it processes the key events based on the callback of AVSession. Implementing play and pause functions through this method also adapts to the wear detection of Bluetooth headsets, with play and pause commands received upon wearing or removing both earpieces. Currently, the following AVSession control commands can be converted: 648 | Control Command| Description | 649 | ------ | -------------------------| 650 | play | Plays the media.| 651 | pause | Pauses the playback.| 652 | stop | Stops the playback.| 653 | playNext | Plays the next media asset.| 654 | playPrevious | Plays the previous media asset.| 655 | fastForward | Fast-forwards.| 656 | rewind | Rewinds.| 657 658 ```ts 659 import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 660 import { BusinessError } from '@kit.BasicServicesKit'; 661 662 @Entry 663 @Component 664 struct Index { 665 @State message: string = 'hello world'; 666 667 build() { 668 Column() { 669 Text(this.message) 670 .onClick(async () => { 671 let context = this.getUIContext().getHostContext() as Context; 672 let type: AVSessionManager.AVSessionType = 'audio'; 673 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 674 // Set the necessary media information. This step is mandatory. Otherwise, the application cannot receive control events. 675 let metadata: AVSessionManager.AVMetadata = { 676 assetId: '0', // Specified by the application, used to identify the media asset in the application media library. 677 title: 'TITLE', 678 mediaImage: 'IMAGE', 679 artist: 'ARTIST' 680 }; 681 session.setAVMetadata(metadata).then(() => { 682 console.info(`SetAVMetadata successfully`); 683 }).catch((err: BusinessError) => { 684 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 685 }); 686 // Generally, logic processing on the player is implemented in the listener. 687 // After the processing is complete, use the setter to synchronize the playback information. For details, see the code snippet above. 688 session.on('play', () => { 689 console.info(`on play , do play task`); 690 // If this command is not supported, do not register it. If the command has been registered but is not used temporarily, use session.off('play') to cancel listening. 691 // After the processing is complete, call SetAVPlayState to report the playback state. 692 }); 693 session.on('pause', () => { 694 console.info(`on pause , do pause task`); 695 // If this command is not supported, do not register it. If the command has been registered but is not used temporarily, use session.off('pause') to cancel listening. 696 // After the processing is complete, call SetAVPlayState to report the playback state. 697 }); 698 }) 699 } 700 .width('100%') 701 .height('100%') 702 } 703 } 704 ``` 705 706- Method 2 707 708 Register the [HandleMediaKeyEvent](../../reference/apis-avsession-kit/arkts-apis-avsession-AVSession.md#onhandlekeyevent10) callback through AVSession. The callback directly forwards the [KeyEvent](../../reference/apis-input-kit/js-apis-keyevent.md). The application is required to identify the type of the key event and implement the corresponding functionalities. Currently, the following key events can be forwarded: 709 710 | Key Type ([KeyCode](../../reference/apis-input-kit/js-apis-keycode.md#keycode))| Description | 711 | ------ | -------------------------| 712 | KEYCODE_MEDIA_PLAY_PAUSE | Play/Pause key.| 713 | KEYCODE_MEDIA_STOP | Stop key.| 714 | KEYCODE_MEDIA_NEXT | Next key.| 715 | KEYCODE_MEDIA_PREVIOUS | Previous key.| 716 | KEYCODE_MEDIA_REWIND | Rewind key.| 717 | KEYCODE_MEDIA_FAST_FORWARD | Fast forward key.| 718 | KEYCODE_MEDIA_PLAY | Play key.| 719 | KEYCODE_MEDIA_PAUSE | Pause key.| 720 721 ```ts 722 import { avSession as AVSessionManager } from '@kit.AVSessionKit'; 723 import { BusinessError } from '@kit.BasicServicesKit'; 724 725 @Entry 726 @Component 727 struct Index { 728 @State message: string = 'hello world'; 729 730 build() { 731 Column() { 732 Text(this.message) 733 .onClick(async () => { 734 let context = this.getUIContext().getHostContext() as Context; 735 let type: AVSessionManager.AVSessionType = 'audio'; 736 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 737 // Set the necessary media information. This step is mandatory. Otherwise, the application cannot receive key events. 738 let metadata: AVSessionManager.AVMetadata = { 739 assetId: '0', // Specified by the application, used to identify the media asset in the application media library. 740 title: 'TITLE', 741 mediaImage: 'IMAGE', 742 artist: 'ARTIST' 743 }; 744 session.setAVMetadata(metadata).then(() => { 745 console.info(`SetAVMetadata successfully`); 746 }).catch((err: BusinessError) => { 747 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 748 }); 749 session.on('handleKeyEvent', (event) => { 750 // Parse the key code. The application must perform logic processing on the player based on the key code. 751 console.info(`on handleKeyEvent, keyCode=${event.key.code}`); 752 }); 753 }) 754 } 755 .width('100%') 756 .height('100%') 757 } 758 } 759 ``` 760 761> **NOTE** 762> 763> 1. Both methods require the accurate configuration of media information AVMetadata and the registration of corresponding control interfaces to receive control commands and key events. 764> 2. Choose either method for integration. Method 1 is recommended. 765 766<!--RP2--> 767<!--RP2End--> 768