• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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