1# AVSession Provider 2 3An audio and video application needs to access the AVSession service as a provider in order to display media information in the controller (for example, Media Controller) and respond to playback control commands delivered by the controller. 4 5## Basic Concepts 6 7- AVMetadata: media data related attributes, including the IDs of the current media asset (assetId), previous media asset (previousAssetId), and next media asset (nextAssetId), title, author, album, writer, and duration. 8 9- AVPlaybackState: playback state attributes, including 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). 10 11## Available APIs 12 13The table below lists the key APIs used by the provider. The APIs use either a callback or promise to return the result. The APIs listed below use a callback. They provide the same functions as their counterparts that use a promise. 14 15For details, see [AVSession Management](../reference/apis/js-apis-avsession.md). 16 17| API| Description| 18| -------- | -------- | 19| createAVSession(context: Context, tag: string, type: AVSessionType, callback: AsyncCallback<AVSession>): void<sup>10+<sup> | Creates an AVSession.<br>Only one AVSession can be created for a UIAbility.| 20| setAVMetadata(data: AVMetadata, callback: AsyncCallback<void>): void<sup>10+<sup> | Sets AVSession metadata.| 21| setAVPlaybackState(state: AVPlaybackState, callback: AsyncCallback<void>): void<sup>10+<sup> | Sets the AVSession playback state.| 22| setLaunchAbility(ability: WantAgent, callback: AsyncCallback<void>): void<sup>10+<sup> | Starts a UIAbility.| 23| getController(callback: AsyncCallback<AVSessionController>): void<sup>10+<sup> | Obtains the controller of the AVSession.| 24| getOutputDevice(callback: AsyncCallback<OutputDeviceInfo>): void<sup>10+<sup> | Obtains the output device information.| 25| activate(callback: AsyncCallback<void>): void<sup>10+<sup> | Activates the AVSession.| 26| deactivate(callback: AsyncCallback<void>): void<sup>10+<sup> | Deactivates this session.| 27| destroy(callback: AsyncCallback<void>): void<sup>10+<sup> | Destroys the AVSession.| 28| setAVQueueItems(items: Array<AVQueueItem>, callback: AsyncCallback<void>): void <sup>10+<sup> | Sets a playlist.| 29| setAVQueueTitle(title: string, callback: AsyncCallback<void>): void<sup>10+<sup> | Sets a name for the playlist.| 30| dispatchSessionEvent(event: string, args: {[key: string]: Object}, callback: AsyncCallback<void>): void<sup>10+<sup> | Dispatches a custom session event.| 31| setExtras(extras: {[key: string]: Object}, callback: AsyncCallback<void>): void<sup>10+<sup> | Sets a custom media packet in the form of a key-value pair.| 32 33## How to Develop 34 35To enable an audio and video application to access the AVSession service as a provider, proceed as follows: 36 371. Call an API in the **AVSessionManager** class to create and activate an **AVSession** object. 38 39 ```ts 40 import AVSessionManager from '@ohos.multimedia.avsession'; 41 42 // Start to create and activate an AVSession object. 43 // Create an AVSession object. 44 let context: Context = getContext(this); 45 async function createSession() { 46 let type: AVSessionManager.AVSessionType = 'audio'; 47 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 48 await session.activate(); 49 console.info(`session create done : sessionId : ${session.sessionId}`); 50 } 51 ``` 52 532. Set AVSession information, which includes: 54 - AVMetadata 55 - AVPlaybackState 56 57 The controller will call an API in the **AVSessionController** class to obtain the information and display or process the information. 58 59 ```ts 60 import AVSessionManager from '@ohos.multimedia.avsession'; 61 import { BusinessError } from '@ohos.base'; 62 63 let context: Context = getContext(this); 64 async function setSessionInfo() { 65 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet in step 1. 66 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', 'audio'); 67 // The player logic that triggers changes in the session metadata and playback state is omitted here. 68 // Set necessary session metadata. 69 let metadata: AVSessionManager.AVMetadata = { 70 assetId: '0', 71 title: 'TITLE', 72 artist: 'ARTIST' 73 }; 74 session.setAVMetadata(metadata).then(() => { 75 console.info(`SetAVMetadata successfully`); 76 }).catch((err: BusinessError) => { 77 console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`); 78 }); 79 // Set the playback state to paused and set isFavorite to false. 80 let playbackState: AVSessionManager.AVPlaybackState = { 81 state:AVSessionManager.PlaybackState.PLAYBACK_STATE_PAUSE, 82 isFavorite:false 83 }; 84 session.setAVPlaybackState(playbackState, (err) => { 85 if (err) { 86 console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`); 87 } else { 88 console.info(`SetAVPlaybackState successfully`); 89 } 90 }); 91 // Set a playlist. 92 let queueItemDescription_1: AVSessionManager.AVMediaDescription = { 93 assetId: '001', 94 title: 'music_name', 95 subtitle: 'music_sub_name', 96 description: 'music_description', 97 mediaImage: "PIXELMAP_OBJECT", 98 extras: {'extras':'any'} 99 }; 100 let queueItem_1: AVSessionManager.AVQueueItem = { 101 itemId: 1, 102 description: queueItemDescription_1 103 }; 104 let queueItemDescription_2: AVSessionManager.AVMediaDescription = { 105 assetId: '002', 106 title: 'music_name', 107 subtitle: 'music_sub_name', 108 description: 'music_description', 109 mediaImage: "PIXELMAP_OBJECT", 110 extras: {'extras':'any'} 111 }; 112 let queueItem_2: AVSessionManager.AVQueueItem = { 113 itemId: 2, 114 description: queueItemDescription_2 115 }; 116 let queueItemsArray = [queueItem_1, queueItem_2]; 117 session.setAVQueueItems(queueItemsArray).then(() => { 118 console.info(`SetAVQueueItems successfully`); 119 }).catch((err: BusinessError) => { 120 console.error(`Failed to set AVQueueItem, error code: ${err.code}, error message: ${err.message}`); 121 }); 122 // Set a name for the playlist. 123 let queueTitle = 'QUEUE_TITLE'; 124 session.setAVQueueTitle(queueTitle).then(() => { 125 console.info(`SetAVQueueTitle successfully`); 126 }).catch((err: BusinessError) => { 127 console.info(`Failed to set AVQueueTitle, error code: ${err.code}, error message: ${err.message}`); 128 }); 129 } 130 ``` 131 1323. Set the UIAbility to be started by the controller. The UIAbility configured here is started when a user operates the UI of the controller, for example, clicking a widget in Media Controller. 133 The UIAbility is set through the **WantAgent** API. For details, see [WantAgent](../reference/apis/js-apis-app-ability-wantAgent.md). 134 135 ```ts 136 import wantAgent from "@ohos.app.ability.wantAgent"; 137 ``` 138 139 ```ts 140 import AVSessionManager from '@ohos.multimedia.avsession'; 141 import wantAgent from '@ohos.app.ability.wantAgent'; 142 143 let context: Context = getContext(this); 144 async function getWantAgent() { 145 let type: AVSessionManager.AVSessionType = 'audio'; 146 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet in step 1. 147 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 148 let wantAgentInfo: wantAgent.WantAgentInfo = { 149 wants: [ 150 { 151 bundleName: 'com.example.musicdemo', 152 abilityName: 'com.example.musicdemo.MainAbility' 153 } 154 ], 155 operationType: wantAgent.OperationType.START_ABILITIES, 156 requestCode: 0, 157 wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG] 158 } 159 wantAgent.getWantAgent(wantAgentInfo).then((agent) => { 160 session.setLaunchAbility(agent); 161 }) 162 } 163 ``` 164 1654. Set a custom session event. The controller performs an operation after receiving the event. 166 167 > **NOTE** 168 > The data set through **dispatchSessionEvent** is not saved in the **AVSession** object or AVSession service. 169 170 ```ts 171 172 import AVSessionManager from '@ohos.multimedia.avsession'; 173 import { BusinessError } from '@ohos.base'; 174 175 let context: Context = getContext(this); 176 async function dispatchSessionEvent() { 177 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet in step 1. 178 let type: AVSessionManager.AVSessionType = 'audio'; 179 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 180 let eventName = 'dynamic_lyric'; 181 await session.dispatchSessionEvent(eventName, {lyric : 'This is my lyric'}).then(() => { 182 console.info(`Dispatch session event successfully`); 183 }).catch((err: BusinessError) => { 184 console.error(`Failed to dispatch session event. Code: ${err.code}, message: ${err.message}`); 185 }) 186 } 187 188 ``` 189 1905. Set a custom media packet. The controller performs an operation after receiving the event. 191 192 > **NOTE** 193 > The data set by using **setExtras** is stored in the AVSession service. The data lifecycle is the same as that of the **AVSession** object, and the controller corresponding to the object can use **getExtras** to obtain the data. 194 195 ```ts 196 import AVSessionManager from '@ohos.multimedia.avsession'; 197 import { BusinessError } from '@ohos.base'; 198 199 let context: Context = getContext(this); 200 async function setExtras() { 201 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet in step 1. 202 let type: AVSessionManager.AVSessionType = 'audio'; 203 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 204 await session.setExtras({extra : 'This is my custom meida packet'}).then(() => { 205 console.info(`Set extras successfully`); 206 }).catch((err: BusinessError) => { 207 console.error(`Failed to set extras. Code: ${err.code}, message: ${err.message}`); 208 }) 209 } 210 ``` 211 2126. Listen for playback control commands or events delivered by the controller, for example, Media Controller. 213 214 Both fixed playback control commands and advanced playback control events can be listened for. 215 216 Listening for Fixed Playback Control Commands 217 218 > **NOTE** 219 > 220 > After the provider registers a listener for fixed playback control commands, the commands will be reflected in **getValidCommands()** of the controller. In other words, the controller determines that the command is valid and triggers the corresponding event as required. To ensure that the playback control commands delivered by the controller can be executed normally, the provider should not use a null implementation for listening. 221 222 Fixed playback control commands on the session side include basic operation commands such as play, pause, previous, and next. For details, see [AVControlCommand](../reference/apis/js-apis-avsession.md). 223 224 ```ts 225 import AVSessionManager from '@ohos.multimedia.avsession'; 226 227 let context: Context = getContext(this); 228 async function setListenerForMesFromController() { 229 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet in step 1. 230 let type: AVSessionManager.AVSessionType = 'audio'; 231 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 232 // Generally, logic processing on the player is implemented in the listener. 233 // After the processing is complete, use the setter to synchronize the playback information. For details, see the code snippet above. 234 session.on('play', () => { 235 console.info(`on play , do play task`); 236 // do some tasks ··· 237 }); 238 session.on('pause', () => { 239 console.info(`on pause , do pause task`); 240 // do some tasks ··· 241 }); 242 session.on('stop', () => { 243 console.info(`on stop , do stop task`); 244 // do some tasks ··· 245 }); 246 session.on('playNext', () => { 247 console.info(`on playNext , do playNext task`); 248 // do some tasks ··· 249 }); 250 session.on('playPrevious', () => { 251 console.info(`on playPrevious , do playPrevious task`); 252 // do some tasks ··· 253 }); 254 session.on('fastForward', () => { 255 console.info(`on fastForward , do fastForward task`); 256 // do some tasks ··· 257 }); 258 session.on('rewind', () => { 259 console.info(`on rewind , do rewind task`); 260 // do some tasks ··· 261 }); 262 263 session.on('seek', (time) => { 264 console.info(`on seek , the seek time is ${time}`); 265 // do some tasks ··· 266 }); 267 session.on('setSpeed', (speed) => { 268 console.info(`on setSpeed , the speed is ${speed}`); 269 // do some tasks ··· 270 }); 271 session.on('setLoopMode', (mode) => { 272 console.info(`on setLoopMode , the loop mode is ${mode}`); 273 // do some tasks ··· 274 }); 275 session.on('toggleFavorite', (assetId) => { 276 console.info(`on toggleFavorite , the target asset Id is ${assetId}`); 277 // do some tasks ··· 278 }); 279 } 280 ``` 281 282 Listening for Advanced Playback Control Events 283 284 The following advanced playback control events can be listened for: 285 286 - **skipToQueueItem**: triggered when an item in the playlist is selected. 287 - **handleKeyEvent**: triggered when a key is pressed. 288 - **outputDeviceChange**: triggered when the output device changes. 289 - **commonCommand**: triggered when a custom playback control command changes. 290 291 ```ts 292 import AVSessionManager from '@ohos.multimedia.avsession'; 293 294 let context: Context = getContext(this); 295 async function setListenerForMesFromController() { 296 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet in step 1. 297 let type: AVSessionManager.AVSessionType = 'audio'; 298 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 299 // Generally, logic processing on the player is implemented in the listener. 300 // After the processing is complete, use the setter to synchronize the playback information. For details, see the code snippet above. 301 session.on('skipToQueueItem', (itemId) => { 302 console.info(`on skipToQueueItem , do skip task`); 303 // do some tasks ··· 304 }); 305 session.on('handleKeyEvent', (event) => { 306 console.info(`on handleKeyEvent , the event is ${JSON.stringify(event)}`); 307 // do some tasks ··· 308 }); 309 session.on('outputDeviceChange', (device) => { 310 console.info(`on outputDeviceChange , the device info is ${JSON.stringify(device)}`); 311 // do some tasks ··· 312 }); 313 session.on('commonCommand', (commandString, args) => { 314 console.info(`on commonCommand , command is ${commandString}, args are ${JSON.stringify(args)}`); 315 // do some tasks ··· 316 }); 317 } 318 ``` 319 3207. Obtain an **AVSessionController** object for this **AVSession** object for interaction. 321 322 ```ts 323 import AVSessionManager from '@ohos.multimedia.avsession'; 324 325 let context: Context = getContext(this); 326 async function createControllerFromSession() { 327 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet in step 1. 328 let type: AVSessionManager.AVSessionType = 'audio'; 329 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 330 331 // Obtain an AVSessionController object for this AVSession object. 332 let controller = await session.getController(); 333 334 // The AVSessionController object can interact with the AVSession object, for example, by delivering a playback control command. 335 let avCommand: AVSessionManager.AVControlCommand = {command:'play'}; 336 controller.sendControlCommand(avCommand); 337 338 // Alternatively, listen for state changes. 339 controller.on('playbackStateChange', 'all', (state) => { 340 341 // do some things 342 }); 343 344 // The AVSessionController object can perform many operations. For details, see the description of the controller. 345 } 346 ``` 347 3488. When the audio and video application exits and does not need to continue playback, cancel the listener and destroy the **AVSession** object. 349 The code snippet below is used for canceling the listener for playback control commands: 350 351 ```ts 352 import AVSessionManager from '@ohos.multimedia.avsession'; 353 354 let context: Context = getContext(this); 355 async function unregisterSessionListener() { 356 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet in step 1. 357 let type: AVSessionManager.AVSessionType = 'audio'; 358 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 359 360 // Cancel the listener of the AVSession object. 361 session.off('play'); 362 session.off('pause'); 363 session.off('stop'); 364 session.off('playNext'); 365 session.off('playPrevious'); 366 session.off('skipToQueueItem'); 367 session.off('handleKeyEvent'); 368 session.off('outputDeviceChange'); 369 session.off('commonCommand'); 370 } 371 ``` 372 373 The code snippet below is used for destroying the AVSession object: 374 375 ```ts 376 import AVSessionManager from '@ohos.multimedia.avsession'; 377 378 let context: Context = getContext(this); 379 async function destroySession() { 380 // It is assumed that an AVSession object has been created. For details about how to create an AVSession object, see the node snippet in step 1. 381 let type: AVSessionManager.AVSessionType = 'audio'; 382 let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type); 383 // Destroy the AVSession object. 384 session.destroy((err) => { 385 if (err) { 386 console.error(`Failed to destroy session. Code: ${err.code}, message: ${err.message}`); 387 } else { 388 console.info(`Destroy : SUCCESS `); 389 } 390 }); 391 } 392 ``` 393