HarmonyOS 调用pipController.startPiP()失败,报文1300013,错误码上说【不要在非全屏窗口下启动画中画】是什么意思?

let pipController: PiPWindow.PiPController | undefined = undefined;
// 开发者应使用该mXComponentController初始化XComponent: XComponent( {id: 'video', type: 'surface', controller: mXComponentController} ),
// 保证XComponent的内容可以被迁移到画中画窗口。
let mXComponentController: XComponentController = new XComponentController();
let config: PiPWindow.PiPConfiguration = {
  context: getContext(this),
  componentController: mXComponentController,
  navigationId: this.navId,
  templateType: PiPWindow.PiPTemplateType.VIDEO_PLAY,
  contentWidth: this.videoSize.width as number,
  contentHeight: this.videoSize.height as number,
  controlGroups: [PiPWindow.VideoPlayControlGroup.FAST_FORWARD_BACKWARD],
  // customUIController: nodeController, // 可选,如果需要在画中画显示内容上方展示自定义UI,可设置该参数。
};

let promise: Promise<PiPWindow.PiPController> = PiPWindow.create(config);
promise.then((data: PiPWindow.PiPController) => {
  pipController = data;
  console.info(`Succeeded in creating pip controller. Data:${data}`);
  let promise : Promise<void> = pipController.startPiP();
  promise.then(() => {
    console.info(`Succeeded in starting pip.`);
  }).catch((err: BusinessError) => {
    console.error(`Failed to start pip. Cause:${err.code}, message:${err.message}`);
  });
}).catch((err: BusinessError) => {
  console.error(`Failed to create pip controller. Cause:${err.code}, message:${err.message}`);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

调用pipController.startPiP()失败,报文1300013,错误码上说【不要在非全屏窗口下启动画中画】是什么意思?

HarmonyOS
2025-01-09 15:46:34
浏览
收藏 0
回答 1
回答 1
按赞同
/
按时间
Heiang

参考demo:

// Page1.ets
// 该页面用于展示画中画功能的基本使用
import { BuilderNode, FrameNode, NodeController, Size, UIContext, PiPWindow } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import media from '@ohos.multimedia.media';

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;
    let fileDescriptor = getContext().resourceManager.getRawFdSync('video1.mp4');
    let avFileDescriptor: media.AVFileDescriptor =
      { fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };
    this.avPlayer.fdSrc = avFileDescriptor
  }

  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();
  }
}
class Params {
  text: string = '';
  constructor(text: string) {
    this.text = text;
  }
}

// 开发者可以通过@Builder装饰器实现布局构建
@Builder
function buildText(params: Params) {
  Column() {
    Text(params.text)
      .fontSize(20)
      .fontColor(Color.Red)
  }
  .width('100%') // 宽度方向充满画中画窗口
  .height('100%') // 高度方向充满画中画窗口
}

// 开发者可通过继承NodeController实现自定义UI控制器
class TextNodeController extends NodeController {
  private message: string;
  private textNode: BuilderNode<[Params]> | null = null;
  constructor(message: string) {
    super();
    this.message = message;
  }

  // 通过BuilderNode加载自定义布局
  makeNode(context: UIContext): FrameNode | null {
    this.textNode = new BuilderNode(context);
    this.textNode.build(wrapBuilder<[Params]>(buildText), new Params(this.message));
    return this.textNode.getFrameNode();
  }

  // 开发者可自定义该方法实现布局更新
  update(message: string) {
    console.log(`update message: ${message}`);
    if (this.textNode !== null) {
      this.textNode.update(new Params(message));
    }
  }
}

@Component
@Entry
export struct Index {
  private surfaceId: string = ''; // surfaceId,用于关联XComponent与视频播放器
  private mXComponentController: XComponentController = new XComponentController();
  private player?: AVPlayerDemo = undefined;
  private pipController?: PiPWindow.PiPController = undefined;
  private nodeController: TextNodeController = new TextNodeController('this is custom UI');
  navId: string = '';
  build() {
    Column() {
      // XComponent控件,用于播放视频流
      XComponent({ id: 'pipDemo', type: 'surface', controller: this.mXComponentController })
        .onLoad(() => {
          this.surfaceId = this.mXComponentController.getXComponentSurfaceId();
          // 需要设置AVPlayer的surfaceId为XComponentController的surfaceId
          this.player = new AVPlayerDemo();
          this.player.setSurfaceID(this.surfaceId)
          this.player.avPlayerLiveDemo(0,'')
        })
        .onDestroy(() => {
        })
        .size({ width: '100%', height: '800px' })
      Row({ space: 20 }) {
        Button('start') // 启动画中画
          .onClick(() => {
            this.startPip();
          })
          .stateStyles({
            pressed: {
              .backgroundColor(Color.Red);
            },
            normal: {
              .backgroundColor(Color.Blue);
            }
          })
        Button('stop') // 停止画中画
          .onClick(() => {
            this.stopPip();
          })
          .stateStyles({
            pressed: {
              .backgroundColor(Color.Red);
            },
            normal: {
              .backgroundColor(Color.Blue);
            }
          })
        Button('updateSize') // 更新视频尺寸
          .onClick(() => {
            // 此处设置的宽高应为媒体内容宽高,需要通过媒体相关接口或回调获取
            // 例如使用AVPlayer播放视频时,可通过videoSizeChange回调获取媒体源更新后的尺寸
            this.updateContentSize(900, 1600);
          })
          .stateStyles({
            pressed: {
              .backgroundColor(Color.Red);
            },
            normal: {
              .backgroundColor(Color.Blue);
            }
          })
      }
      .size({ width: '100%', height: 60 })
      .justifyContent(FlexAlign.SpaceAround)
    }
    .justifyContent(FlexAlign.Center)
    .height('100%')
    .width('100%')
  }

  startPip() {
    if (!PiPWindow.isPiPEnabled()) {
      console.error(`picture in picture disabled for current OS`);
      return;
    }
    let config: PiPWindow.PiPConfiguration = {
      context: getContext(this),
      componentController: this.mXComponentController,
      // 当前page导航id
      // 1、UIAbility使用Navigation管理页面,需要设置Navigation控件的id属性,并将该id设置给画中画控制器,确保还原场景下能够从画中画窗口恢复到原页面
      // 2、UIAbility使用Router管理页面时(画中画场景不推荐该导航方式),无需设置navigationId。注意:该场景下启动画中画后,不要进行页面切换,否则还原场景可能出现异常
      // 3、UIAbility只有单页面时,无需设置navigationId,还原场景下也能够从画中画窗口恢复到原页面
      navigationId: this.navId,
      templateType: PiPWindow.PiPTemplateType.VIDEO_PLAY, // 对于视频通话、视频会议等场景,需要设置相应的模板类型
      contentWidth: 1920, // 可选,创建画中画控制器时系统可通过XComponent组件大小设置画中画窗口比例
      contentHeight: 1080, // 可选,创建画中画控制器时系统可通过XComponent组件大小设置画中画窗口比例
      controlGroups:[PiPWindow.VideoPlayControlGroup.FAST_FORWARD_BACKWARD], // 可选,对于视频通话、视频会议和视频直播场景,可通过该属性选择对应模板类型下需显示的的控件组
      // customUIController: this.nodeController, // 可选,如果需要在画中画显示内容上方展示自定义UI,可设置该参数。
    };
    // 步骤1:创建画中画控制器,通过create接口创建画中画控制器实例
    let promise : Promise<PiPWindow.PiPController> = PiPWindow.create(config);
    promise.then((controller : PiPWindow.PiPController) => {
      this.pipController = controller;
      // 步骤1:初始化画中画控制器
      this.initPipController();
      // 步骤2:通过startPiP接口启动画中画
      this.pipController.startPiP().then(() => {
        console.info(`Succeeded in starting pip.`);
      }).catch((err: BusinessError) => {
        console.error(`Failed to start pip. Cause:${err.code}, message:${err.message}`);
      });
    }).catch((err: BusinessError) => {
      console.error(`Failed to create pip controller. Cause:${err.code}, message:${err.message}`);
    });
  }

  initPipController() {
    if (!this.pipController) {
      return;
    }
    // 步骤1:通过setAutoStartEnabled接口设置是否需要在应用返回桌面时自动启动画中画,注册stateChange和controlPanelActionEvent回调
    this.pipController.setAutoStartEnabled(false /*or true if necessary*/); // 默认为false
    this.pipController.on('stateChange', (state: PiPWindow.PiPState, reason: string) => {
      this.onStateChange(state, reason);
    });
    this.pipController.on('controlPanelActionEvent', (event: PiPWindow.PiPActionEventType, status?: number) => {
      this.onActionEvent(event, status);
    });
  }

  onStateChange(state: PiPWindow.PiPState, reason: string) {
    let curState: string = '';
    switch(state) {
      case PiPWindow.PiPState.ABOUT_TO_START:
        curState = "ABOUT_TO_START";
        break;
      case PiPWindow.PiPState.STARTED:
        curState = "STARTED";
        break;
      case PiPWindow.PiPState.ABOUT_TO_STOP:
        curState = "ABOUT_TO_STOP";
        break;
      case PiPWindow.PiPState.STOPPED:
        curState = "STOPPED";
        break;
      case PiPWindow.PiPState.ABOUT_TO_RESTORE:
        curState = "ABOUT_TO_RESTORE";
        break;
      case PiPWindow.PiPState.ERROR:
        curState = "ERROR";
        break;
      default:
        break;
    }
  }

  onActionEvent(event: PiPWindow.PiPActionEventType, status?: number) {
    switch (event) {
      case 'playbackStateChanged':
      // 开始或停止视频
        if (status === 0) {
          // 停止视频
          this.player?.pause()
        } else if (status === 1) {
          // 播放视频
          this.player?.start()
        }
        break;
      case 'nextVideo':
      // 播放上一个视频
        break;
      case 'previousVideo':
      // 播放下一个视频
        break;
      default:
        break;
    }
  }

  // 步骤3:视频内容变化时,向画中画控制器更新视频尺寸信息,用于调整画中画窗口比例
  updateContentSize(width: number, height: number) {
    if (this.pipController) {
      this.pipController.updateContentSize(width, height);
    }
  }

  // 步骤4:当不再需要显示画中画时,通过stopPiP接口关闭画中画
  stopPip() {
    if (this.pipController) {
      let promise : Promise<void> = this.pipController.stopPiP();
      promise.then(() => {
        console.info(`Succeeded in stopping pip.`);
        this.pipController?.off('stateChange'); // 如果已注册stateChange回调,停止画中画时取消注册该回调
        this.pipController?.off('controlPanelActionEvent'); // 如果已注册controlPanelActionEvent回调,停止画中画时取消注册该回调
      }).catch((err: BusinessError) => {
        console.error(`Failed to stop pip. Cause:${err.code}, message:${err.message}`);
      });
    }
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.
  • 256.
  • 257.
  • 258.
  • 259.
  • 260.
  • 261.
  • 262.
  • 263.
  • 264.
  • 265.
  • 266.
  • 267.
  • 268.
  • 269.
  • 270.
  • 271.
  • 272.
  • 273.
  • 274.
  • 275.
  • 276.
  • 277.
  • 278.
  • 279.
  • 280.
  • 281.
  • 282.
  • 283.
  • 284.
  • 285.
  • 286.
  • 287.
  • 288.
  • 289.
  • 290.
  • 291.
  • 292.
  • 293.
  • 294.
  • 295.
  • 296.
  • 297.
  • 298.
  • 299.
  • 300.
  • 301.
  • 302.
  • 303.
  • 304.
  • 305.
  • 306.
  • 307.
  • 308.
  • 309.
  • 310.
  • 311.
  • 312.
  • 313.
  • 314.
  • 315.
  • 316.
  • 317.
  • 318.
  • 319.
  • 320.
  • 321.
  • 322.
  • 323.
  • 324.
  • 325.
  • 326.
  • 327.
  • 328.
  • 329.
  • 330.
  • 331.
  • 332.
  • 333.
  • 334.
  • 335.
  • 336.
  • 337.
  • 338.
  • 339.
  • 340.
  • 341.
  • 342.
  • 343.
  • 344.
  • 345.
  • 346.
  • 347.
  • 348.
  • 349.
  • 350.
  • 351.
  • 352.
  • 353.
  • 354.
  • 355.
  • 356.
  • 357.
  • 358.
  • 359.
分享
微博
QQ
微信
回复
2025-01-09 18:24:48
相关问题
HarmonyOS 画中画
504浏览 • 1回复 待解决
HarmonyOS 画中画视频无法播放
716浏览 • 1回复 待解决
webview错误码105 是什么错误
1680浏览 • 1回复 待解决
HarmonyOS 画中画无法指定窗体大小
630浏览 • 1回复 待解决
HarmonyOS 定位失败 错误码3301200:
805浏览 • 1回复 待解决
是否支持画中画播放能力?
251浏览 • 0回复 待解决
是什么意思
3137浏览 • 1回复 待解决
TiDB Server具体是什么意思
3921浏览 • 1回复 待解决
HarmonyOS @ohos.PiPWindow开启画中画示例
656浏览 • 1回复 待解决
HarmonyOS 音视频画中画功能demo
754浏览 • 1回复 待解决
DevEco的日志如下是什么意思
1628浏览 • 0回复 待解决
MongoDB中的分片是什么意思
4129浏览 • 1回复 待解决
鸿蒙的signature权限是什么意思
8737浏览 • 1回复 待解决
startAbility跳转失败返回错误码16000001
3000浏览 • 1回复 待解决
调用广告接口,返回错误码21800003
1369浏览 • 1回复 待解决
鸿蒙提供的画中画功能要怎么实现?
1740浏览 • 1回复 待解决
HarmonyOS 错误码7400201
983浏览 • 1回复 待解决
是什么意思
3074浏览 • 1回复 待解决
提问
该提问已有0人参与 ,帮助了0人