This document summarizes typical issues encountered by audio and video apps during local media session integration with AVSession Kit, along with their diagnosis and resolution methods. You can use AVSession management error codes and HiLog logs to further diagnose issues.
Symptom
An exception is thrown when createAVSession is called, and the session is not created successfully.
Possible Causes
Solution
Check whether a live AVSession already exists. If necessary, call destroy to release the old session before creating a new one. Before creation, you can also call getAVSession to check whether the current app has already created a session object, and then decide whether to destroy the old session or reuse the existing one.
In scenarios involving frequent creation and destruction, listen for the on('sessionDestroy') event through the media session controller, and create a new AVSession object only after receiving the old session destruction callback.
import { avSession } from '@kit.AVSessionKit';
async destroyAndRecreateAVSession(context: Context) {
let videoSession: avSession.AVSession;
let avSessionController: avSession.AVSessionController;
try {
// Create an AVSession for the first time and obtain its controller.
videoSession = await avSession.createAVSession(context, 'VIDEO_SESSION', 'video');
avSessionController = await videoSession.getController();
// Register a session destruction listener. The callback is triggered after the session is destroyed.
avSessionController.on('sessionDestroy', async () => {
// Create an AVSession for the second time. Re-create a session of the same type after destruction.
videoSession = await avSession.createAVSession(context, 'VIDEO_SESSION', 'video');
// Destroy the AVSession for the second time.
await videoSession.destroy();
});
// Destroy the AVSession for the first time, which triggers the sessionDestroy callback above.
await videoSession.destroy();
} catch (err) {
console.error(`AVSession create Error: Code: ${err.code}, message: ${err.message}`);
}
} It is recommended to obtain the context through this.getUIContext().getHostContext() as Context to avoid passing undefined or a context that does not belong to the current UIAbility.
Ensure that type is a valid value defined in AVSessionType.
Ensure that all required parameters are valid non-null values. For example, avoid passing invalid values such as an empty string for tag.
Symptom
After the app is switched to the background, audio and video playback is forcibly paused by the system, and the user cannot continue listening.
Possible Causes
Solution
Refer to Accessing AVSession in Background Playback to complete AVSession integration.
Apply for an AUDIO_PLAYBACK type continuous task (ArkTS).
Use a class member variable to hold the session instance, and release it only when the app process ends or the playback service exits.
Check the related causes in AVSession Creation Failure one by one to ensure that the app holds a valid session.
Before the app is relegated to the background, call setBackgroundPlayMode to set the background playback mode (BackgroundPlayMode), which informs the system whether to continue playback when the app is relegated to the background:
For apps with AVSessionType set to audio, the default value is ENABLE_BACKGROUND_PLAY; for apps with the type set to video, the default value is DISABLE_BACKGROUND_PLAY. If a video app needs to support background audio playback, you must explicitly set it to ENABLE_BACKGROUND_PLAY. If the app provides a "whether background playback is supported" switch, the background playback mode set must be consistent with the switch state; otherwise, the app may be forcibly paused after being relegated to the background, or the system Live View may display incorrectly. The following is a setup example:
import { avSession } from '@kit.AVSessionKit';
import { BusinessError } from '@kit.BasicServicesKit';
// Assume that currentAVSession has been created and held.
async setBackgroundPlayMode(currentAVSession: avSession.AVSession) {
try {
await currentAVSession.setBackgroundPlayMode(avSession.BackgroundPlayMode.ENABLE_BACKGROUND_PLAY);
console.info(' Succeeded in setBackgroundPlayMode');
} catch (err) {
let error = err as BusinessError;
console.error(`setBackgroundPlayMode BusinessError: code: ${error.code}, message: ${error.message}`);
}
} For more details, see Setting the Background Playback Mode.
Symptom
The app has created an AVSession, but the Media Control Center does not display the corresponding media information or control bar.
Possible Causes
A call-type app does not use the call session type, or the system version/app classification does not meet the requirements.
In versions earlier than HarmonyOS 6.0.0, AVSession accessed by call apps will not be displayed in the Media Controller.
Solution
When a call app integrates AVSession, the session type (AVSessionType) must be set to voice_call or video_call.
In HarmonyOS 6.0.0 and later versions, when an app is released as a business or social app on AppGallery, the message "In a call..." can be displayed in the Media Controller, and the AVCastPicker component can be used to switch the call device. For details, see Switching Call Output Devices.
Symptom
When control buttons (play, pause, previous, next, etc.) are tapped in the media control center, there is no response, and neither the app nor the media control interface is updated. Alternatively, the actual playback state of the app is out of sync with the state displayed in the media control center — for example, the app is playing but the media control still shows paused.
Possible Causes
Solution
Symptom
After tapping the play button in the media control center, the playback progress bar rewinds and flickers.
Possible Causes
The player startup delay causes progress inconsistency. After the play button is tapped, the playback progress bar in the media control center starts timing immediately, while the player in the app has not actually started playback yet, causing its progress to lag behind the media control center. When the app subsequently synchronizes the progress, the progress value is smaller than the elapsed time tracked by the media control center, resulting in the progress bar rewinding and flickering.
Solution
Before the player starts playback, call setAVPlaybackState to set the state to PLAYBACK_STATE_BUFFERING (buffering). After the player actually starts playback, synchronize the state and progress.
import { avSession } from '@kit.AVSessionKit';
import { media } from '@kit.MediaKit';
// avPlayer is the player instance created through media.createAVPlayer(), and currentAVSession is the created AVSession object.
async listenAVPlayer(avPlayer: media.AVPlayer, currentAVSession: avSession.AVSession) {
// Listen for AVPlayer state machine transitions in advance. After actual playback starts (entering the playing state), synchronize the actual state and progress.
avPlayer.on('stateChange', async (state: string) => {
if (state === 'playing') {
let playingState: avSession.AVPlaybackState = {
state: avSession.PlaybackState.PLAYBACK_STATE_PLAY,
speed: 1.0,
// currentTime is the current actual playback progress of AVPlayer, in milliseconds (ms).
position: { elapsedTime: avPlayer.currentTime, updateTime: (new Date()).getTime() }
};
await currentAVSession.setAVPlaybackState(playingState);
}
});
// After receiving a playback command and before AVPlayer actually starts playback, set the media control state to buffering to prevent the media control progress bar from starting to count ahead of time.
let bufferingState: avSession.AVPlaybackState = {
state: avSession.PlaybackState.PLAYBACK_STATE_BUFFERING,
speed: 0,
position: { elapsedTime: 0, updateTime: (new Date()).getTime() }
};
await currentAVSession.setAVPlaybackState(bufferingState);
await avPlayer.play();
}