HarmonyOS鸿蒙Next中创建AVSession之后在通知栏没有显示
HarmonyOS鸿蒙Next中创建AVSession之后在通知栏没有显示 在接入AVSession之后,在通知栏没有显示音频相关信息,想实现例如音乐播放器那种控制模块,显示到通知栏。下面是我的demo
import { BusinessError } from '@kit.BasicServicesKit';
import { avSession, avSession as AVSessionManager } from '@kit.AVSessionKit';
@Entry
@Component
struct Index {
aboutToAppear(): void {
createSession()
}
build() {
Column() {
Button('开启音频通知栏')
.onClick(() => {
setSessionInfo()
})
}
}
}
// 开始创建并激活媒体会话
// 创建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}`);
}
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}`);
});
}
更多关于HarmonyOS鸿蒙Next中创建AVSession之后在通知栏没有显示的实战教程也可以访问 https://www.itying.com/category-93-b0.html
AVSession播控中心,您可以参考示例:https://gitee.com/harmonyos_samples/media-provider,您想实现音乐播放器控制台在通知栏显示,需要做一个通知,在通知上添加几个按钮。当前通知可以通过设置actionButtons设置按键,规格当前最多三个按钮。
您截图这种,可以使用AVPlayer+AVSession实现,AVPlayer文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-media-V5#avplayer9,AVSession文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-avsession-V5#avsession10,简易demo如下:
import { media } from '@kit.MediaKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { avSession } from '@kit.AVSessionKit';
const TAG = 'AVPlayerDemo';
@Entry
@Component
struct AVPlayerDemo {
private surfaceId: string = ''; // surfaceId,用于关联XComponent与视频播放器
private mXComponentController: XComponentController = new XComponentController();
private avPlayer: media.AVPlayer | undefined = undefined;
private currentAVSession: avSession.AVSession | undefined = undefined;
private curSessionId: string = '';
private avsessionController: avSession.AVSessionController | undefined = undefined;
private playbackState: avSession.AVPlaybackState = {
state: avSession.PlaybackState.PLAYBACK_STATE_PLAY, // 播放状态
position: {
elapsedTime: 0, // 已经播放的位置,以ms为单位
updateTime: 0, // 应用更新当前位置的时间戳,以ms为单位
},
speed: 1.0, // 可选,默认是1.0,播放的倍速,按照应用内支持的speed进行设置,系统不做校验
duration: 0, // 资源的时长,以ms为单位
loopMode: avSession.LoopMode.LOOP_MODE_SEQUENCE, // 循环模式
};
aboutToAppear(): void {
// 创建avplayer
this.initAvPlayer()
// 初始化AVSession
this.createAVSession();
}
initAvPlayer() {
media.createAVPlayer().then((avPlayer: media.AVPlayer) => {
this.avPlayer = avPlayer;
this.playerCallback(this.avPlayer);
this.avPlayer.url = 'http://fotiletest2.oss-cn-hangzhou.aliyuncs.com/f86ee6ff04f94c4d922936faedbfca06';
})
}
// 注册avplayer回调函数
playerCallback(avPlayer: media.AVPlayer) {
avPlayer.on('timeUpdate', (time: number) => {
if (this.currentAVSession) {
this.playbackState.position = {
elapsedTime: time, // 已经播放的位置,以ms为单位
updateTime: (new Date()).getTime(), // 应用更新当前位置的时间戳,以ms为单位
};
this.currentAVSession.setAVPlaybackState(this.playbackState);
}
})
// error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程
avPlayer.on('error', (err: BusinessError) => {
console.error(TAG, `Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
avPlayer.reset(); // 调用reset重置资源,触发idle状态
})
// 状态机变化回调函数
avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
switch (state) {
case 'idle': // 成功调用reset接口后触发该状态机上报
console.info(TAG, 'AVPlayer state idle called.');
break;
case 'initialized': // avplayer 设置播放源后触发该状态上报
console.info(TAG, 'AVPlayer state initialized called.');
avPlayer.surfaceId = this.surfaceId;
avPlayer.prepare();
break;
case 'prepared': // prepare调用成功后上报该状态机
console.info(TAG, 'AVPlayer state prepared called.');
await this.startAVSession();
break;
case 'completed': // prepare调用成功后上报该状态机
console.info(TAG, 'AVPlayer state completed called.');
break;
case 'playing': // play成功调用后触发该状态机上报
console.info(TAG, 'AVPlayer state playing called.');
break;
case 'paused': // pause成功调用后触发该状态机上报
console.info(TAG, 'AVPlayer state paused called.');
break;
case 'stopped': // stop接口成功调用后触发该状态机上报
console.info(TAG, 'AVPlayer state stopped called.');
break;
case 'released':
console.info(TAG, 'AVPlayer state released called.');
break;
default:
console.info(TAG, 'AVPlayer state unknown called.');
break;
}
})
}
async createAVSession() {
await avSession.createAVSession(getContext(this), 'AVPlayerDemo', 'video').then((data: avSession.AVSession) => {
console.info(`AVPlayerDemo CreateAVSession : SUCCESS : sessionId = ${data.sessionId}`);
this.currentAVSession = data;
this.curSessionId = data.sessionId;
this.setAVSessionCallback(data);
}).catch((err: BusinessError) => {
console.error(`AVPlayerDemo CreateAVSession BusinessError: code: ${err.code}, message: ${err.message}`);
});
}
setAVSessionCallback(curAvSession: avSession.AVSession) {
// 播放
curAvSession.on('play', () => {
console.info(`AVPlayerDemo AVSession on play entry`);
this.avPlayer?.play()
});
// 暂停
curAvSession.on('pause', () => {
console.info(`AVPlayerDemo AVSession on pause entry`);
if (this.avPlayer) {
this.avPlayer.pause();
}
});
// 停止
curAvSession.on('stop', () => {
console.info(`AVPlayerDemo AVSession on stop entry`);
this.avPlayer?.stop();
});
// 下一个
curAvSession.on('playNext', () => {
console.info(`AVPlayerDemo AVSession on playNext entry`);
});
// 上一个
curAvSession.on('playPrevious', () => {
console.info(`AVPlayerDemo AVSession on playPrevious entry`);
});
}
async startAVSession() {
if (!this.currentAVSession) {
console.error('AVPlayerDemo currentAVSession is undefined.')
return;
}
let metadata: avSession.AVMetadata = this.generateAVMetadata();
await this.currentAVSession.setAVMetadata(metadata).then(() => {
console.info(`AVPlayerDemo SetAVMetadata successfully`);
}).catch((err: BusinessError) => {
console.error(`AVPlayerDemo SetAVMetadata BusinessError: code: ${err.code}, message: ${err.message}`);
});
this.playbackState.state = avSession.PlaybackState.PLAYBACK_STATE_PREPARE;
this.playbackState.duration = this.avPlayer?.duration;
this.currentAVSession.setAVPlaybackState(this.playbackState);
this.currentAVSession.getController().then((avcontroller: avSession.AVSessionController) => {
this.avsessionController = avcontroller;
console.info(`AVPlayerDemo GetController : SUCCESS : sessionid : ${avcontroller.sessionId}`);
}).catch((err: BusinessError) => {
console.error(`AVPlayerDemo GetController BusinessError: code: ${err.code}, message: ${err.message}`);
});
await this.currentAVSession.activate().then(() => {
console.info(`AVPlayerDemo Activate : SUCCESS `);
}).catch((err: BusinessError) => {
console.error(`AVPlayerDemo Activate BusinessError: code: ${err.code}, message: ${err.message}`);
});
}
private generateAVMetadata() {
let metadata: avSession.AVMetadata = {
assetId: "121278",
title: "lose yourself",
artist: "Eminem",
author: "ST",
album: "Slim shady",
writer: "ST",
composer: "ST",
duration: this.avPlayer?.duration, // 媒体时长,单位毫秒(ms)
mediaImage: '', // 图片的像素数据或者图片路径地址(本地路径或网络路径)
subtitle: "8 Mile",
description: "Rap",
previousAssetId: "121277",
nextAssetId: "121279"
};
return metadata;
}
build() {
Column({ space: 20 }) {
XComponent({
id: 'xComponent',
type: XComponentType.SURFACE,
controller: this.mXComponentController
})
.onLoad(() => {
this.mXComponentController.setXComponentSurfaceRect({
offsetX: 0,
offsetY: 0,
surfaceWidth: 1920,
surfaceHeight: 1080
});
this.surfaceId = this.mXComponentController.getXComponentSurfaceId()
})
.width('100%')
.height('800px')
Button("播放")
.onClick(() => {
this.avPlayer?.play()
})
}
.height('100%')
.width('100%')
}
}
更多关于HarmonyOS鸿蒙Next中创建AVSession之后在通知栏没有显示的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
AVSession播控中心,您可以参考示例:https://gitee.com/harmonyos_samples/media-provider,您想实现音乐播放器控制台在通知栏显示,需要做一个通知,在通知上添加几个按钮。当前通知可以通过设置actionButtons设置按键,规格当前最多三个按钮。
您截图这种,可以使用AVPlayer+AVSession实现,AVPlayer文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-media-V5#avplayer9,AVSession文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-avsession-V5#avsession10,简易demo如下:
import { media } from '[@kit](/user/kit).MediaKit';
import { BusinessError } from '[@kit](/user/kit).BasicServicesKit';
import { avSession } from '[@kit](/user/kit).AVSessionKit';
const TAG = 'AVPlayerDemo';
[@Entry](/user/Entry)
[@Component](/user/Component)
struct AVPlayerDemo {
private surfaceId: string = ''; // surfaceId,用于关联XComponent与视频播放器
private mXComponentController: XComponentController = new XComponentController();
private avPlayer: media.AVPlayer | undefined = undefined;
private currentAVSession: avSession.AVSession | undefined = undefined;
private curSessionId: string = '';
private avsessionController: avSession.AVSessionController | undefined = undefined;
private playbackState: avSession.AVPlaybackState = {
state: avSession.PlaybackState.PLAYBACK_STATE_PLAY, // 播放状态
position: {
elapsedTime: 0, // 已经播放的位置,以ms为单位
updateTime: 0, // 应用更新当前位置的时间戳,以ms为单位
},
speed: 1.0, // 可选,默认是1.0,播放的倍速,按照应用内支持的speed进行设置,系统不做校验
// bufferedTime: 14000, // 可选,资源缓存的时间,以ms为单位
duration: 0, // 资源的时长,以ms为单位
loopMode: avSession.LoopMode.LOOP_MODE_SEQUENCE, // 循环模式
};
aboutToAppear(): void {
//创建avplayer
this.initAvPlayer()
// 初始化AVSession
this.createAVSession();
}
initAvPlayer() {
media.createAVPlayer().then((avPlayer: media.AVPlayer) => {
this.avPlayer = avPlayer;
this.playerCallback(this.avPlayer);
this.avPlayer.url = 'http://fotiletest2.oss-cn-hangzhou.aliyuncs.com/f86ee6ff04f94c4d922936faedbfca06';
})
}
// 注册avplayer回调函数
playerCallback(avPlayer: media.AVPlayer) {
avPlayer.on('timeUpdate', (time: number) => {
if (this.currentAVSession) {
this.playbackState.position = {
elapsedTime: time, // 已经播放的位置,以ms为单位
updateTime: (new Date()).getTime(), // 应用更新当前位置的时间戳,以ms为单位
};
this.currentAVSession.setAVPlaybackState(this.playbackState);
}
})
// error回调监听函数,当avPlayer在操作过程中出现错误时调用 reset接口触发重置流程
avPlayer.on('error', (err: BusinessError) => {
console.error(TAG,`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
avPlayer.reset(); // 调用reset重置资源,触发idle状态
})
// 状态机变化回调函数
avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
switch (state) {
case 'idle': // 成功调用reset接口后触发该状态机上报
console.info(TAG,'AVPlayer state idle called.');
break;
case 'initialized': // avplayer 设置播放源后触发该状态上报
console.info(TAG,'AVPlayer state initialized called.');
avPlayer.surfaceId = this.surfaceId;
avPlayer.prepare();
break;
case 'prepared': // prepare调用成功后上报该状态机
console.info(TAG,'AVPlayer state prepared called.');
await this.startAVSession();
break;
case 'completed': // prepare调用成功后上报该状态机
console.info(TAG,'AVPlayer state completed called.');
break;
case 'playing': // play成功调用后触发该状态机上报
console.info(TAG,'AVPlayer state playing called.');
break;
case 'paused': // pause成功调用后触发该状态机上报
console.info(TAG,'AVPlayer state paused called.');
break;
case 'stopped': // stop接口成功调用后触发该状态机上报
console.info(TAG,'AVPlayer state stopped called.');
break;
case 'released':
console.info(TAG,'AVPlayer state released called.');
break;
default:
console.info(TAG,'AVPlayer state unknown called.');
break;
}
})
}
async createAVSession() {
await avSession.createAVSession(getContext(this), 'AVPlayerDemo', 'video').then((data: avSession.AVSession) => {
console.info(`AVPlayerDemo CreateAVSession : SUCCESS : sessionId = ${data.sessionId}`);
this.currentAVSession = data;
this.curSessionId = data.sessionId;
this.setAVSessionCallback(data);
}).catch((err: BusinessError) => {
console.error(`AVPlayerDemo CreateAVSession BusinessError: code: ${err.code}, message: ${err.message}`);
});
}
setAVSessionCallback(curAvSession: avSession.AVSession) {
// 播放
curAvSession.on('play', () => {
console.info(`AVPlayerDemo AVSession on play entry`);
this.avPlayer?.play()
});
// 暂停
curAvSession.on('pause', () => {
console.info(`AVPlayerDemo AVSession on pause entry`);
if (this.avPlayer) {
this.avPlayer.pause();
}
});
// 停止
curAvSession.on('stop', () => {
console.info(`AVPlayerDemo AVSession on stop entry`);
this.avPlayer?.stop();
});
// 下一个
curAvSession.on('playNext', () => {
console.info(`AVPlayerDemo AVSession on playNext entry`);
});
// 上一个
curAvSession.on('playPrevious', () => {
console.info(`AVPlayerDemo AVSession on playPrevious entry`);
});
}
async startAVSession() {
if (!this.currentAVSession) {
console.error('AVPlayerDemo currentAVSession is undefined.')
return;
}
let metadata: avSession.AVMetadata = this.generateAVMetadata();
await this.currentAVSession.setAVMetadata(metadata).then(() => {
console.info(`AVPlayerDemo SetAVMetadata successfully`);
}).catch((err: BusinessError) => {
console.error(`AVPlayerDemo SetAVMetadata BusinessError: code: ${err.code}, message: ${err.message}`);
});
this.playbackState.state = avSession.PlaybackState.PLAYBACK_STATE_PREPARE;
this.playbackState.duration = this.avPlayer?.duration;
this.currentAVSession.setAVPlaybackState(this.playbackState);
this.currentAVSession.getController().then((avcontroller: avSession.AVSessionController) => {
this.avsessionController = avcontroller;
console.info(`AVPlayerDemo GetController : SUCCESS : sessionid : ${avcontroller.sessionId}`);
}).catch((err: BusinessError) => {
console.error(`AVPlayerDemo GetController BusinessError: code: ${err.code}, message: ${err.message}`);
});
await this.currentAVSession.activate().then(() => {
console.info(`AVPlayerDemo Activate : SUCCESS `);
}).catch((err: BusinessError) => {
console.error(`AVPlayerDemo Activate BusinessError: code: ${err.code}, message: ${err.message}`);
});
}
private generateAVMetadata() {
let metadata: avSession.AVMetadata = {
assetId: "121278",
title: "lose yourself",
artist: "Eminem",
author: "ST",
album: "Slim shady",
writer: "ST",
composer: "ST",
duration: this.avPlayer?.duration, // 媒体时长,单位毫秒(ms)
mediaImage: 'https://img20.360buyimg.com/img/jfs/t1/241153/31/4968/64736/65e53e56Fd3868b6e/b595d41ca8447ea4.jpg', // 图片的像素数据或者图片路径地址(本地路径或网络路径)
subtitle: "8 Mile",
description: "Rap",
previousAssetId: "121277",
nextAssetId: "121279"
};
return metadata;
}
build() {
Column({ space: 20 }) {
XComponent({
id: 'xComponent',
type: XComponentType.SURFACE,
controller: this.mXComponentController
})
.onLoad(() => {
this.mXComponentController.setXComponentSurfaceRect({
offsetX:0,
offsetY:0,
surfaceWidth: 1920,
surfaceHeight: 1080
});
this.surfaceId = this.mXComponentController.getXComponentSurfaceId()
})
.width('100%')
.height('800px')
Button("播放")
.onClick(() => {
this.avPlayer?.play()
})
}
.height('100%')
.width('100%')
}
}在HarmonyOS鸿蒙Next中,创建AVSession后通知栏未显示的原因可能涉及以下几点:
- 首先,检查AVSession是否已正确初始化并启动。确保调用了
AVSession.create()和AVSession.activate()方法。 - 其次,确认AVSession的元数据(如标题、艺术家、专辑等)是否已正确设置,因为通知栏显示依赖于这些信息。可以通过
AVMetadata类进行设置。 - 此外,检查权限配置,确保应用具有
ohos.permission.NOTIFICATION_CONTROLLER权限,以便在通知栏显示媒体控制界面。 - 如果以上步骤均无误,可能是系统通知栏的实现限制或Bug,需进一步排查系统日志或更新HarmonyOS版本。
在HarmonyOS鸿蒙Next中,创建AVSession后通知栏未显示,可能的原因包括:未正确设置AVSession的属性(如AVMetadata和AVSessionDescriptor),或未调用setActive(true)激活会话。确保在创建AVSession时,正确配置了媒体信息(如标题、艺术家等),并调用setActive(true)。此外,检查应用的通知权限是否已开启,确保系统能够正常显示媒体控制通知。

