HarmonyOS avplayer组件播放视频的时候,横屏,然后再浮窗,浮窗必定播放失败

HarmonyOS
3天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
shlp

xc+avplayer无缝切换的示例可以参考下:

EntryAbility页面:

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { AVPlayerDemo } from '../pages/AVPlayerDemo';
export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  }
  onDestroy(): void {
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
  }
  onWindowStageCreate(windowStage: window.WindowStage): void {
    // Main window is created, set main page for this ability
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    windowStage.loadContent('pages/XCAvplayer', (err) => {
      if (err.code) {
        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      AppStorage.setOrCreate('player', new AVPlayerDemo());
      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
    });
  }
  onWindowStageDestroy(): void {
    // Main window is destroyed, release UI related resources
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }
  onForeground(): void {
    // Ability has brought to foreground
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
  }
  onBackground(): void {
    // Ability has back to background
    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

XCAvplayer页面:

import { myVideoSourceDate, VideoSource } from './myVideoSourceDate';
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('文案0', 'https://xxx.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%')
  }
}

VideoComponent页面:

import { AVPlayerDemo } from './AVPlayerDemo';
import { VideoSource } from './myVideoSourceDate';
import window from '@ohos.window';
import { BusinessError } from '@ohos.base';
import { router } from '@kit.ArkUI';

@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;
  // player: AVPlayerDemo = new AVPlayerDemo();
  player: AVPlayerDemo = AppStorage.get('player') as 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() {
    // 通过显隐控制控制其他listItrem是否展示
    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.setSurfaceID(this.mXComponentController.getXComponentSurfaceId());
            this.player_changed = !this.player_changed;
            this.player.avPlayerLiveDemo(0, this.item.url);
          })
        Row() {
          Button(this.isLayoutFullScreen ? '退出全屏' : '点击全屏')
            .onClick(() => {
              this.fangDaIndex = this.index
              this.isLayoutFullScreen = !this.isLayoutFullScreen;
              this.setR(this.isLayoutFullScreen ? 4 : 1)
              this.setFullScreen(this.isLayoutFullScreen)
            })
            .backgroundColor(this.bkColor)
          Button('跳转页面')
            .onClick(() => {
              this.player.pause();
              router.pushUrl({
                url: 'pages/PageSec'
              })
            })
            .backgroundColor(this.bkColor)
        }
      }
      .height(this.isLayoutFullScreen ? '100%' : 200)
    }
    .width('100%')
  }
}

PageSec页面:

import { AVPlayerDemo } from './AVPlayerDemo'

@Entry
@Component
struct PageSec {
  private surfaceId: string = '';
  xComponentController: XComponentController = new XComponentController();
  @State rect: SurfaceRect | null = null;
  player: AVPlayerDemo = AppStorage.get('player') as AVPlayerDemo;

  build() {
    Column() {
      XComponent({
        id: 'xcomponent',
        type: XComponentType.SURFACE,
        controller: this.xComponentController
      })
        .onLoad(() => {
          let surfaceRect: SurfaceRect = {
            offsetX: 0,
            offsetY: 0,
            surfaceWidth: 1200,
            surfaceHeight: 500
          };
          this.xComponentController.setXComponentSurfaceRect(surfaceRect);
          this.surfaceId = this.xComponentController.getXComponentSurfaceId()
          this.player.setSurfaceID(this.surfaceId);
          this.player.start();
        })
    }
    .width('100%')
  }
}

myVideoSourceDate页面:

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;
  }
}

import media from '@ohos.multimedia.media';
import { BusinessError } from '@ohos.base';

export class AVPlayerDemo {
  private count: number = 0;
  private surfaceID: string = '';
  private url: string = '';
  private avPlayer: media.AVPlayer | undefined;

  // 注册avplayer回调函数。
  setAVPlayerCallback() {
    // seek操作结果回调函数。
    this.avPlayer?.on('seekDone', (seekDoneTime: number) => {
      console.info(`AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
    })
    // error回调监听函数,当avplayer在操作过程中出现错误时,调用reset接口触发重置流程。
    this.avPlayer?.on('error', (err: BusinessError) => {
      console.error(`Invoke avPlayer failed, code is ${err.code}, message is ${err.message}`);
      this.avPlayer?.reset();
    })
    // 状态机变化回调函数。
    this.avPlayer?.on('stateChange', async (state: string, reason: media.StateChangeReason) => {
      switch (state) {
        case 'idle':
          console.info('AVPlayer state idle called.');
          this.avPlayer?.release();
          break;
        case 'initialized':
          console.info('AVPlayer state initialized called.');
          if (this.avPlayer != null && this.avPlayer != undefined) {
            this.avPlayer.surfaceId = this.surfaceID;
          }
          this.avPlayer?.prepare();
          break;
        case 'prepared':
          console.info('AVPlayer state prepared called.');
          if (this.count === 0 || this.count === 1) {
            console.info('AVPlayer start to play.');
            if (this.avPlayer != null && this.avPlayer != undefined) {
              this.avPlayer.surfaceId = this.surfaceID;
            }
            this.avPlayer?.play();
          }
          break;
        case 'playing':
          console.info('AVPlayer state playing called.');
          if (this.avPlayer != null && this.avPlayer != undefined) {
            this.avPlayer.surfaceId = this.surfaceID
          }
          this.avPlayer?.play();
          break;
        case 'paused':
          console.info('AVPlayer state paused called.');
          this.avPlayer?.pause();
          break;
        case 'completed':
          console.info('AVPlayer state paused called.');
          this.avPlayer?.stop();
          break;
        case 'stopped':
          console.info('AVPlayer state stopped called.');
          this.avPlayer?.reset();
          break;
        case 'released':
          console.info('AVPlayer state released called.' + this.surfaceID);
          break;
        default:
          break;
      }
    })
  }

  async avPlayerLiveDemo(count: number, url ?: string, avplayer ?: media.AVPlayer) {
    this.count = count;
    if (url != undefined) {
      this.url = url;
    }
    this.avPlayer = await media.createAVPlayer();
    this.setAVPlayerCallback();
    this.avPlayer.url = url;
  }

  destroy() {
    this.avPlayer?.stop()
    this.avPlayer?.release()
    this.avPlayer = undefined
  }

  setSurfaceID(surface_id: string) {
    console.log('setSurfaceID : ' + surface_id);
    this.surfaceID = surface_id;
  }

  getAvPlayer(): media.AVPlayer | undefined {
    return this.avPlayer;
  }

  getSurfaceID(): string {
    return this.surfaceID;
  }

  setUrl(url: string) {
    this.url = url;
  }

  getUrl(): string {
    return this.url
  }

  start() {
    this.avPlayer?.play()
  }

  pause() {
    this.avPlayer?.pause();
  }
}
分享
微博
QQ
微信
回复
3天前
相关问题
如何实现全局效果
1741浏览 • 1回复 待解决
HarmonyOS 应用内点击事件相关
39浏览 • 1回复 待解决
HarmonyOS 播放视频时候禁止息
33浏览 • 1回复 待解决
AVPlayer实现视频播放
1071浏览 • 1回复 待解决
avplayer播放视频demo
1615浏览 • 1回复 待解决
HarmonyOS AvPlayer视频播放速度问题
492浏览 • 1回复 待解决
HarmonyOS 播放问题
390浏览 • 1回复 待解决
应用如何适配华为悬浮?
2672浏览 • 1回复 待解决
HarmonyOS 视频播放AVPlayer解码异常
42浏览 • 1回复 待解决
HarmonyOS video如何播放
318浏览 • 1回复 待解决