请参考示例如下://AVPlayerDemo.ets import media from '@ohos.multimedia.media'; import {BusinessError} from '@ohos.base'; import { ifaa } from '@kit.OnlineAuthenticationKit'; import { common } from '@kit.AbilityKit'; export class AVPlayerDemo { private count: number = 0; private surfaceID: string = ''; // surfaceID用于播放画面显示,具体的值需要通过Xcomponent接口获取,相关文档链接见上面Xcomponent创建方法。 private isSeek: boolean = true; // 用于区分模式是否支持seek操作。 private avPlayer: media.AVPlayer | undefined = undefined; setSurfaceID(surface_id: string){ console.log('setSurfaceID : ' + surface_id); this.surfaceID = surface_id; } // 注册avplayer回调函数。 setAVPlayerCallback(avPlayer: media.AVPlayer) { // seek操作结果回调函数。 avPlayer.on('seekDone', (seekDoneTime: number) => { console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`); }) // error回调监听函数,当avplayer在操作过程中出现错误时,调用reset接口触发重置流程。 avPlayer.on('error', (err: BusinessError) => { console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`); avPlayer.reset(); }) // 状态机变化回调函数。 avPlayer.on('stateChange', async (state: string, reason: media.StateChangeReason) => { switch (state) { case 'idle': // 成功调用reset接口后触发该状态机上报。 console.info('AVPlayer state idle called.'); avPlayer.release(); // 调用release接口销毁实例对象。 break; case 'initialized': // avplayer 设置播放源后触发该状态上报。 console.info('AVPlayer state initialized called.'); avPlayer.surfaceId = this.surfaceID; // 设置显示画面,当播放的资源为纯音频时无需设置。 avPlayer.prepare(); break; case 'prepared': // prepared调用成功后上报该状态机。 console.info('AVPlayer state prepared called.'); avPlayer.play(); break; case 'playing': // play成功调用后触发该状态机上报。 console.info('AVPlayer state playing called.'); break; case 'paused': // pause成功调用后触发该状态机上报。 console.info('AVPlayer state paused called.'); // avPlayer.play(); // 再次播放接口开始播放。 break; case 'completed': //播放接口后触发该状态机上报。 console.info('AVPlayer state paused called.'); avPlayer.play(); // 调用播放接口接口。 break; case 'stopped': // stop接口后触发该状态机上报。 console.info('AVPlayer state stopped called.'); avPlayer.reset(); // 调用reset接口初始化avplayer状态。 break; case 'released': //播放接口后触发该状态机上报。 console.info('AVPlayer state released called.'); break; default: break; } }) } // 通过url设置网络地址来实现播放直播码流。 async avPlayerLiveDemo(count : number ,url: string){ this.count = count // async avPlayerLiveDemo(){ // 创建avPlayer实例对象 this.avPlayer = await media.createAVPlayer(); // 创建状态机变化回调函数。 this.setAVPlayerCallback(this.avPlayer); let context = getContext(this) as common.UIAbilityContext; let fileDescriptor = await context.resourceManager.getRawFd(url); let avFileDescriptor: media.AVFileDescriptor = { fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length }; this.avPlayer.fdSrc = avFileDescriptor; } async release() { this.avPlayer?.reset(); } getStage(): string { if (this.avPlayer !== undefined) { return this.avPlayer.state; } return 'undefined'; } }//index.ets import { myVideoSourceDate, VideoSource } from './myVideoSourceData'; import { VideoComponent } from './VideoComponent'; @Entry @Component struct XCAvplayer { private data: myVideoSourceDate = new myVideoSourceDate([]); @State isLayoutFullScreen : boolean = false; @State fangDaIndex : number = -1; aboutToAppear(): void { let list: VideoSource[] = [ new VideoSource("文案1", "video1.mp4"), new VideoSource("文案2", "video2.mp4"), new VideoSource("文案3", "video3.mp4"), new VideoSource("文案4", "video4.mp4") ]; console.log("myAppliction is Appear") this.data = new myVideoSourceDate(list); } build() { Scroll() { Column() { List() { LazyForEach(this.data, (item: VideoSource,index : number) => { ListItem() { VideoComponent({item : item, isLayoutFullScreen : this.isLayoutFullScreen, index : index , fangDaIndex : this.fangDaIndex}) .visibility(this.isLayoutFullScreen && this.fangDaIndex !== index ? Visibility.None : Visibility.Visible) } }, (item: string) => item) }.cachedCount(5).scrollBar(BarState.Off).edgeEffect(this.isLayoutFullScreen ? EdgeEffect.None : EdgeEffect.Spring) } } .edgeEffect(this.isLayoutFullScreen ? EdgeEffect.None : EdgeEffect.Spring) .width('100%') } }//myVideoSourceDate.ets export class myVideoSourceDate implements IDataSource { videoList: VideoSource[] = []; constructor(videoList: VideoSource[]) { this.videoList = videoList; } totalCount(): number { return this.videoList.length; } getData(index: number): VideoSource { return this.videoList[index]; } registerDataChangeListener(listener: DataChangeListener): void { } unregisterDataChangeListener(listener: DataChangeListener): void { } } @Observed export class VideoSource { text: string; url: string; constructor(text: string,url: string) { this.text = text; this.url = url; } }//VideoComponent.ets import { AVPlayerDemo } from './AVPlayerDemo'; import { VideoSource } from './myVideoSourceData'; import window from '@ohos.window'; import { BusinessError } from '@ohos.base'; import { router } from '@kit.ArkUI'; let isPlaying: AVPlayerDemo[] = []; @Component export struct VideoComponent { @ObjectLink item: VideoSource; index : number = -1; @Link isLayoutFullScreen: boolean; @Link fangDaIndex : number; @State bkColor: Color = Color.Red mXComponentController: XComponentController = new XComponentController(); @State player_changed: boolean = false; @State isLandScape: boolean = false; player?: AVPlayerDemo; // 设置窗口方向 setR(orientation: number) { window.getLastWindow(getContext(this)).then((win) => { win.setPreferredOrientation(orientation).then((data) => { console.log('setWindowOrientation: ' + orientation + ' Succeeded. Data: ' + JSON.stringify(data)); }).catch((err: string) => { console.log('setWindowOrientation: Failed. Cause: ' + JSON.stringify(err)); }); }).catch((err: string) => { console.log('setWindowOrientation: Failed to obtain the top window. Cause: ' + JSON.stringify(err)); }); } //设置沉浸式窗口 setFullScreen(isLayoutFullScreen: boolean) { window.getLastWindow(getContext(this)).then((win) => { win.setWindowLayoutFullScreen(isLayoutFullScreen, (err: BusinessError) => { const errCode: number = err.code; if (errCode) { console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err)); return; } console.info('Succeeded in setting the window layout to full-screen mode.'); }); }).catch((err: string) => { console.log('setWindowOrientation: Failed to obtain the top window. Cause: ' + JSON.stringify(err)); }); } build() { //通过显隐控制控制其他listItem是否展示 Column() { Text(this.item.text) .visibility(this.isLayoutFullScreen === false ? Visibility.Visible : Visibility.None) Stack() { XComponent({ id: 'video_player_id', type: XComponentType.SURFACE, controller: this.mXComponentController }) .onLoad(() => { this.player = new AVPlayerDemo(); this.player.setSurfaceID(this.mXComponentController.getXComponentSurfaceId()); }) .height(this.isLayoutFullScreen ? (this.isLandScape ? '100%' : 200) : "100%") Row() { Button(this.player && (this.player.getStage() === 'playing') ? '播放中' : '开始') .onClick(async () => { if (isPlaying.length !== 0) { let play = isPlaying.pop(); await play?.release(); } if (this.player) { this.player.avPlayerLiveDemo(0, this.item.url); isPlaying.push(this.player); } }) .backgroundColor(this.bkColor) Button("点击全屏") .onClick(() => { this.fangDaIndex = this.index; this.isLayoutFullScreen = true; this.setFullScreen(this.isLayoutFullScreen) }) .backgroundColor(this.bkColor) Button("退出全屏") .onClick(() => { this.setR(1); this.isLayoutFullScreen = false; this.isLandScape = false; this.setFullScreen(this.isLayoutFullScreen) }) .backgroundColor(this.bkColor) Button("横屏") .onClick(() => { this.fangDaIndex = this.index; this.setR(4); this.isLandScape = true; this.isLayoutFullScreen = true; this.setFullScreen(this.isLayoutFullScreen) }) .backgroundColor(this.bkColor) Button("退出横屏") .onClick(() => { this.setR(1); this.isLandScape = false; }) .backgroundColor(this.bkColor) } } .backgroundColor(Color.Black) .height(this.isLayoutFullScreen ? "100%" : 200) } .onVisibleAreaChange([0.2, 1.0], async (isVisible: boolean, currentRatio: number) => { if (!isVisible && currentRatio < 0.2) { if (this.player && isPlaying.length !== 0 && this.player === isPlaying[0]) { console.info('onVisibleAreaChange') this.player.release(); isPlaying[0].release(); isPlaying.pop(); } } }) .width('100%') } }
请参考示例如下: