交互过程
本地媒体会话的数据源均在设备本地,交互过程如图所示。
此过程中涉及两大角色,媒体会话提供方和媒体会话控制方。
说明
媒体会话控制方为系统应用,三方应用可以成为媒体会话提供方。
本地媒体会话中,媒体会话提供方通过媒体会话管理器和媒体会话控制方进行信息交互:
-
媒体会话提供方通过AVSessionManager创建AVSession对象。
-
媒体会话提供方通过AVSession对象,设置会话元数据(媒体ID、标题、媒体时长等)、会话播放属性(播放状态、播放倍速、播放位置等)等。
-
媒体会话控制方通过AVSessionManager创建AVSessionController对象。
-
媒体会话控制方通过AVSessionController对象可以监听对应会话元数据变化、播放属性变化等。
-
媒体会话控制方通过AVSessionController对象还可以向媒体会话发送控制命令。
-
媒体会话提供方通过AVSession对象可以监听来自媒体会话控制方的控制命令,例如:“play”播放、“playNext”播放下一首、“fastForward”快进、 “setSpeed”设置播放倍数等。
媒体会话管理器
媒体会话管理器(AVSessionManager),提供了管理AVSession的能力,可以创建AVSession、创建AVSessionController、发送系统控制事件,也支持对AVSession的状态进行监听。
实际上,AVSessionManager与AVSession、AVSessionController对象不同,并不是一个具体的对象,它是媒体会话的根命名域。在实际编程过程中,可以通过如下方式引入:
import { avSession as AVSessionManager } from '@kit.AVSessionKit';
根命名域中的所有方法都可以作为AVSessionManager的方法。
例如,媒体会话提供方通过AVSessionManager创建媒体会话的示例如下所示:
// 创建session
let context: Context = getContext(this);
async function createSession() {
let session: AVSessionManager.AVSession = await AVSessionManager.createAVSession(context, 'SESSION_NAME', 'audio');
console.info(`session create done : sessionId : ${session.sessionId}`);
}
更多关于AVSessionManager的方法,可以参考API文档。
媒体会话提供方
音视频应用在实现音视频功能的同时,需要作为媒体会话提供方接入媒体会话,在媒体会话控制方(例如播控中心)中展示媒体相关信息,及响应媒体会话控制方下发的播控命令。
基本概念
-
媒体会话元数据(AVMetadata): 用于描述媒体数据相关属性,包含标识当前媒体的ID(assetId),上一首媒体的ID(previousAssetId),下一首媒体的ID(nextAssetId),标题(title),专辑作者(author),专辑名称(album),词作者(writer),媒体时长(duration)等属性。
-
媒体播放状态(AVPlaybackState):用于描述媒体播放状态的相关属性,包含当前媒体的播放状态(state)、播放位置(position)、播放倍速(speed)、缓冲时间(bufferedTime)、循环模式(loopMode)、是否收藏(isFavorite)、正在播放的媒体Id(activeItemId)、自定义媒体数据(extras)等属性。
接口说明
媒体会话提供方使用的关键接口如下表所示。接口返回值有两种返回形式:callback和promise,下表中为callback形式接口,promise和callback只是返回值方式不一样,功能相同。
更多API说明请参见API文档。
开发步骤
音视频应用作为媒体会话提供方接入媒体会话的基本步骤如下所示:
- 通过AVSessionManager的方法创建并激活媒体会话。
import { avSession as AVSessionManager } from '@kit.AVSessionKit';
// 开始创建并激活媒体会话
// 创建session
let context: Context = getContext(this);
async function createSession() {
let type: AVSessionManager.AVSessionType = 'audio';
let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type);
await session.activate();
console.info(`session create done : sessionId : ${session.sessionId}`);
}
-
跟随媒体信息的变化,及时设置媒体会话信息。需要设置的媒体会话信息主要包括:
- 媒体会话元数据AVMetadata。
- 媒体播放状态AVPlaybackState。
音视频应用设置的媒体会话信息,会被媒体会话控制方通过AVSessionController相关方法获取后进行显示或处理。
import { avSession as AVSessionManager } from '@kit.AVSessionKit';
import { BusinessError } from '@kit.BasicServicesKit';
let context: Context = getContext(this);
async function setSessionInfo() {
// 假设已经创建了一个session,如何创建session可以参考之前的案例
let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', 'audio');
// 播放器逻辑··· 引发媒体信息与播放状态的变更
// 设置必要的媒体信息
let metadata: AVSessionManager.AVMetadata = {
assetId: '0', // 由应用指定,用于标识应用媒体库里的媒体
title: 'TITLE',
mediaImage: 'IMAGE',
artist: 'ARTIST'
};
session.setAVMetadata(metadata).then(() => {
console.info(`SetAVMetadata successfully`);
}).catch((err: BusinessError) => {
console.error(`Failed to set AVMetadata. Code: ${err.code}, message: ${err.message}`);
});
// 简单设置一个播放状态 - 暂停 未收藏
let playbackState: AVSessionManager.AVPlaybackState = {
state:AVSessionManager.PlaybackState.PLAYBACK_STATE_PAUSE,
isFavorite:false
};
session.setAVPlaybackState(playbackState, (err) => {
if (err) {
console.error(`Failed to set AVPlaybackState. Code: ${err.code}, message: ${err.message}`);
} else {
console.info(`SetAVPlaybackState successfully`);
}
});
// 设置一个播放列表
let queueItemDescription_1: AVSessionManager.AVMediaDescription = {
assetId: '001',
title: 'music_name',
subtitle: 'music_sub_name',
description: 'music_description',
mediaImage: "PIXELMAP_OBJECT",
extras: {'extras':'any'}
};
let queueItem_1: AVSessionManager.AVQueueItem = {
itemId: 1,
description: queueItemDescription_1
};
let queueItemDescription_2: AVSessionManager.AVMediaDescription = {
assetId: '002',
title: 'music_name',
subtitle: 'music_sub_name',
description: 'music_description',
mediaImage: "PIXELMAP_OBJECT",
extras: {'extras':'any'}
};
let queueItem_2: AVSessionManager.AVQueueItem = {
itemId: 2,
description: queueItemDescription_2
};
let queueItemsArray = [queueItem_1, queueItem_2];
session.setAVQueueItems(queueItemsArray).then(() => {
console.info(`SetAVQueueItems successfully`);
}).catch((err: BusinessError) => {
console.error(`Failed to set AVQueueItem, error code: ${err.code}, error message: ${err.message}`);
});
// 设置媒体播放列表名称
let queueTitle = 'QUEUE_TITLE';
session.setAVQueueTitle(queueTitle).then(() => {
console.info(`SetAVQueueTitle successfully`);
}).catch((err: BusinessError) => {
console.info(`Failed to set AVQueueTitle, error code: ${err.code}, error message: ${err.message}`);
});
}
-
设置用于被媒体会话控制方拉起的UIAbility。当用户操作媒体会话控制方的界面时,例如点击播控中心的卡片,可以拉起此处配置的UIAbility。
设置UIAbility时通过WantAgent接口实现,更多关于WantAgent的信息请参考WantAgent。
import { wantAgent } from '@kit.AbilityKit';
import { avSession as AVSessionManager } from '@kit.AVSessionKit';
import { wantAgent } from '@kit.AbilityKit';
let context: Context = getContext(this);
async function getWantAgent() {
let type: AVSessionManager.AVSessionType = 'audio';
// 假设已经创建了一个session,如何创建session可以参考之前的案例
let session = await AVSessionManager.createAVSession(context, 'SESSION_NAME', type);
let wantAgentInfo: wantAgent.WantAgentInfo = {
wants: [
{
bundleName: 'com.example.musicdemo',
abilityName: 'MainAbility'
}
],
operationType: wantAgent.OperationType.START_ABILITIES,
requestCode: 0,
wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
}
wantAgent.getWantAgent(wantAgentInfo).then((agent) => {
session.setLaunchAbility(agent);
})
}
- 设置一个即时的自定义会话事件,以供媒体控制方接收到事件后进行相应的操作。
说明
通过dispatchSessionEvent方法设置的数据不会保存在会话对象或AVSession服务中。
import { avSession as AVSessionManager } from '@kit.AVSessionKit';
import { BusinessError } from '@kit.BasicServicesKit';
let context: C