开源 Arkts 鸿蒙应用 开发(十三)音频--MP3播放

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

相关链接:

开源 Arkts 鸿蒙应用 开发(一)工程文件分析-CSDN博客

开源 Arkts 鸿蒙应用 开发(二)封装库.har制作和应用-CSDN博客

开源 Arkts 鸿蒙应用 开发(三)Arkts的介绍-CSDN博客

开源 Arkts 鸿蒙应用 开发(四)布局和常用控件-CSDN博客

开源 Arkts 鸿蒙应用 开发(五)控件组成和复杂控件-CSDN博客

开源 Arkts 鸿蒙应用 开发(六)数据持久--文件和首选项存储-CSDN博客

开源 Arkts 鸿蒙应用 开发(七)数据持久--sqlite关系数据库-CSDN博客

开源 Arkts 鸿蒙应用 开发(八)多媒体--相册和相机-CSDN博客

开源 Arkts 鸿蒙应用 开发(九)通讯--tcp客户端-CSDN博客

开源 Arkts 鸿蒙应用 开发(十)通讯--Http-CSDN博客

开源 Arkts 鸿蒙应用 开发(十一)证书和包名修改-CSDN博客

开源 Arkts 鸿蒙应用 开发(十二)传感器的使用-CSDN博客

推荐链接:

开源 java android app 开发(一)开发环境的搭建-CSDN博客

开源 java android app 开发(二)工程文件结构-CSDN博客

开源 java android app 开发(三)GUI界面布局和常用组件-CSDN博客

开源 java android app 开发(四)GUI界面重要组件-CSDN博客

开源 java android app 开发(五)文件和数据库存储-CSDN博客

开源 java android app 开发(六)多媒体使用-CSDN博客

开源 java android app 开发(七)通讯之Tcp和Http-CSDN博客

开源 java android app 开发(八)通讯之Mqtt和Ble-CSDN博客

开源 java android app 开发(九)后台之线程和服务-CSDN博客

开源 java android app 开发(十)广播机制-CSDN博客

开源 java android app 开发(十一)调试、发布-CSDN博客

开源 java android app 开发(十二)封库.aar-CSDN博客

推荐链接:

开源C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客

开源 C# .net mvc 开发(三)WEB内外网访问(VS发布、IIS配置网站、花生壳外网穿刺访问)_c# mvc 域名下不可訪問內網,內網下可以訪問域名-CSDN博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示_c#工程结构-CSDN博客

开源 Arkts 鸿蒙应用 开发(十)通讯--Http数据传输-CSDN博客开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客

本章内容主HarmonyOS next 系统上的本机音频怎么播放,实现了一个简易的音乐播放器,可以播放App资源文件夹下的3首mp3。

1.代码结构分析

2.文件分析说明

3.显示效果

一、代码结构分析

需要添加和修改的文件如下:

entry/src/main/ets/pages 文件夹下需要有App.ets,Index.et,List.ets。

entry/src/main/resoures/base/profile/main_pages.json 页面配置文件也需要修改

entry/src/main/resoures/rawfile 文件加下需要有3个.mp3文件

二、文件分析说明

2.1 List.ets显示了音乐的列表,选择以后,跳转到Index.ets页面播放相应的音乐

以下为 List.ets代码

复制代码
import { router } from '@kit.ArkUI';
import storage from './App';


@Entry(storage)
@Component
struct Index {

  @LocalStorageLink('myData') myData: string = 'test_01';
  // 列表数据 - 字符串数组
  private dataList: string[] = [
    "test_01",
    "test_02",
    "test_03",

  ];


  build() {
    Column() {
      // 列表标题
      Text('音乐列表')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 10 })

      // ListView 实现
      List({ space: 10 }) {
        ForEach(this.dataList, (item: string) => {
          ListItem() {
            Text(item)
              .fontSize(18)
              .width('100%')
              .height(60)
              .textAlign(TextAlign.Center)
              .backgroundColor(Color.White)
              .borderRadius(8)
          }
          .onClick(() => {
            this.myData = item.toString();
            console.log("myData1",this.myData);
            // 点击跳转到详情页,传递当前项内容
            router.push({
              url: 'pages/Index',

            });
          })
        })
      }
      .width('100%')
      .layoutWeight(1)  // 占据剩余空间
      .margin(10)
      .divider({
        strokeWidth: 1,
        color: '#EEEEEE',
        startMargin: 20,
        endMargin: 20
      })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}

2.2 Index.ets 文件,通过AVPlayer可以实现端到端播放原始媒体资源。

1)播放的全流程包含:创建AVPlayer,设置播放资源,设置播放参数(音量/倍速/焦点模式),播放控制(播放/暂停/跳转/停止),重置,销毁资源。

播放状态变化示意图

2)函数分析

AVPlayer封装

使用@ohos.multimedia.media模块的AVPlayer实现媒体播放

提供play()、pause()、seek()、setSpeed()等基本控制方法

通过fdSrc从资源文件加载媒体

状态管理:

监听stateChange事件处理播放器状态(idle/initialized/prepared/playing等)

播放器初始化

复制代码
async avSetupAudio() {
  // 获取资源文件描述符
  let fileDescriptor = await this.context.resourceManager.getRawFd(this.fileName);
  let avFileDescriptor = { fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };

  // 创建AVPlayer实例
  this.avPlayer = await media.createAVPlayer();
  
  // 设置回调
  await this.setAVPlayerCallback(...);
  
  // 设置播放源
  this.avPlayer.fdSrc = avFileDescriptor;
}

状态回调处理

复制代码
this.avPlayer.on('stateChange', async (state, reason) => {
  switch (state) {
    case 'initialized':
      // 设置Surface并准备播放
      this.avPlayer.surfaceId = this.surfaceId;
      this.avPlayer.prepare();
      break;
    case 'prepared':
      // 开始播放并设置初始倍速
      this.avPlayer.play();
      break;
    case 'playing':
      // 更新UI状态
      break;
    // 其他状态处理...
  }
});

3)以下为Index.ets代码

复制代码
/*
 * Copyright (c) 2023-2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import display from '@ohos.display';
import emitter from '@ohos.events.emitter';
import { common } from '@kit.AbilityKit';
import media from '@ohos.multimedia.media';
import { router } from '@kit.ArkUI';
import storage from './App';

const PROPORTION = 0.99; // 占屏幕比例
const SURFACE_W = 0.9; // 表面宽比例
const SURFACE_H = 1.78; // 表面高比例
const SET_INTERVAL = 100; // interval间隔时间
const TIME_ONE = 60000;
const TIME_TWO = 1000;
const SPEED_ZERO = 0;
const SPEED_ONE = 1;
const SPEED_TWO = 2;
const SPEED_THREE = 3;
const SPEED_COUNT = 4;
let innerEventFalse: emitter.InnerEvent = {
  eventId: 1,
  priority: emitter.EventPriority.HIGH
};
let innerEventTrue: emitter.InnerEvent = {
  eventId: 2,
  priority: emitter.EventPriority.HIGH
};
let innerEventWH: emitter.InnerEvent = {
  eventId: 3,
  priority: emitter.EventPriority.HIGH
};

@Entry(storage)
@Component
struct Index {
  @LocalStorageLink('myData') myData: string = '';

  tag: string = 'AVPlayManager';
  private xComponentController: XComponentController = new XComponentController();
  private avPlayer: media.AVPlayer | null = null;
  private surfaceId: string = '';
  private intervalID: number = -1;
  private seekTime: number = -1;
  private context: common.UIAbilityContext | undefined = undefined;
  private count: number = 0;


  @State fileName: string = 'test_01.mp3';
  @State isSwiping: boolean = false; // 用户滑动过程中
  @State isPaused: boolean = true; // 暂停播放
  @State XComponentFlag: boolean = false;
  @State speedSelect: number = 0; // 倍速选择
  @State speedList: Resource[] = [$r('app.string.video_speed_1_0X'), $r('app.string.video_speed_1_25X'), $r('app.string.video_speed_1_75X'), $r('app.string.video_speed_2_0X')];
  @StorageLink('durationTime') durationTime: number = 0; // 视频总时长
  @StorageLink('currentTime') currentTime: number = 0; // 视频当前时间
  @StorageLink('speedName') speedName: Resource = $r('app.string.video_speed_1_0X');
  @StorageLink('speedIndex') speedIndex: number = 0; // 倍速索引
  @State surfaceW: number | null = null;
  @State surfaceH: number | null = null;
  @State percent: number = 0;
  @State windowWidth: number = 300;
  @State windowHeight: number = 200;

  getDurationTime(): number {
    return this.durationTime;
  }

  getCurrentTime(): number {
    return this.currentTime;
  }

  timeConvert(time: number): string {
    let min: number = Math.floor(time / TIME_ONE);
    let second: string = ((time % TIME_ONE) / TIME_TWO).toFixed(0);
    // return `${min}:${(+second < TIME_THREE ? '0' : '') + second}`;
    second = second.padStart(2, '0');
    return `${min}:${second}`;
  }

  async msleepAsync(ms: number): Promise<boolean> {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(true)
      }, ms)
    })
  }

  async avSetupAudio() {
    // 通过UIAbilityContext的resourceManager成员的getRawFd接口获取媒体资源播放地址。
    // 返回类型为{fd,offset,length},fd为HAP包fd地址,offset为媒体资源偏移量,length为播放长度。
    if (this.context == undefined) return;
    let fileDescriptor = await this.context.resourceManager.getRawFd(this.fileName);
    let avFileDescriptor: media.AVFileDescriptor =
      { fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };

    if (this.avPlayer) {
      console.info(`${this.tag}: init avPlayer release2createNew`);
      this.avPlayer.release();
      await this.msleepAsync(1500);
    }
    // 创建avPlayer实例对象
    this.avPlayer = await media.createAVPlayer();

    // 创建状态机变化回调函数
    await this.setAVPlayerCallback((avPlayer: media.AVPlayer) => {
      this.percent = avPlayer.width / avPlayer.height;
      this.setVideoWH();
      this.durationTime = this.getDurationTime();
      setInterval(() => { // 更新当前时间
        if (!this.isSwiping) {
          this.currentTime = this.getCurrentTime();
        }
      }, SET_INTERVAL);
    });

    // 为fdSrc赋值触发initialized状态机上报
    this.avPlayer.fdSrc = avFileDescriptor;
  }

  avPlay(): void {
    if (this.avPlayer) {
      try {
        this.avPlayer.play();
      } catch (e) {
        console.error(`${this.tag}: avPlay = ${JSON.stringify(e)}`);
      }
    }
  }

  avPause(): void {

    if (this.avPlayer) {
      try {
        this.avPlayer.pause();
        console.info(`${this.tag}: avPause==`);
      } catch (e) {
        console.error(`${this.tag}: avPause== ${JSON.stringify(e)}`);
      }
    }
  }

  async avSeek(seekTime: number, mode: SliderChangeMode): Promise<void> {
    if (this.avPlayer) {
      try {
        console.info(`${this.tag}: videoSeek  seekTime== ${seekTime}`);
        this.avPlayer.seek(seekTime, 2);
        this.currentTime = seekTime;
      } catch (e) {
        console.error(`${this.tag}: videoSeek== ${JSON.stringify(e)}`);
      }
    }
  }

  avSetSpeed(speed: number): void {
    if (this.avPlayer) {
      try {
        this.avPlayer.setSpeed(speed);
        console.info(`${this.tag}: avSetSpeed enum ${speed}`);
      } catch (e) {
        console.error(`${this.tag}: avSetSpeed == ${JSON.stringify(e)}`);
      }
    }
  }

  // 注册avplayer回调函数
  async setAVPlayerCallback(callback: (avPlayer: media.AVPlayer) => void, vType?: number): Promise<void> {
    // seek操作结果回调函数
    if (this.avPlayer == null) {
      console.error(`${this.tag}: avPlayer has not init!`);
      return;
    }
    this.avPlayer.on('seekDone', (seekDoneTime) => {
      console.info(`${this.tag}: setAVPlayerCallback AVPlayer seek succeeded, seek time is ${seekDoneTime}`);
    });
    this.avPlayer.on('speedDone', (speed) => {
      console.info(`${this.tag}: setAVPlayerCallback AVPlayer speedDone, speed is ${speed}`);
    });
    // error回调监听函数,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程
    this.avPlayer.on('error', (err) => {
      console.error(`${this.tag}: setAVPlayerCallback Invoke avPlayer failed ${JSON.stringify(err)}`);
      if (this.avPlayer == null) {
        console.error(`${this.tag}: avPlayer has not init on error`);
        return;
      }
      this.avPlayer.reset();
    });
    // 状态机变化回调函数
    this.avPlayer.on('stateChange', async (state, reason) => {
      if (this.avPlayer == null) {
        console.info(`${this.tag}: avPlayer has not init on state change`);
        return;
      }
      switch (state) {
        case 'idle': // 成功调用reset接口后触发该状态机上报
          console.info(`${this.tag}: setAVPlayerCallback AVPlayer state idle called.`);
          break;
        case 'initialized': // avplayer 设置播放源后触发该状态上报
          console.info(`${this.tag}: setAVPlayerCallback AVPlayer state initialized called.`);
          if (this.surfaceId) {
            this.avPlayer.surfaceId = this.surfaceId; // 设置显示画面,当播放的资源为纯音频时无需设置
            console.info(`${this.tag}: setAVPlayerCallback this.avPlayer.surfaceId = ${this.avPlayer.surfaceId}`);
            this.avPlayer.prepare();
          }
          break;
        case 'prepared': // prepare调用成功后上报该状态机
          console.info(`${this.tag}: setAVPlayerCallback AVPlayer state prepared called.`);
          this.avPlayer.on('bufferingUpdate', (infoType: media.BufferingInfoType, value: number) => {
            console.info(`${this.tag}: bufferingUpdate called, infoType value: ${infoType}, value:${value}}`);
          })
          this.durationTime = this.avPlayer.duration;
          this.currentTime = this.avPlayer.currentTime;
          this.avPlayer.play(); // 调用播放接口开始播放
          console.info(`${this.tag}:
            setAVPlayerCallback speedSelect: ${this.speedSelect}, duration: ${this.durationTime}`);
          if (this.speedSelect != -1) {
            switch (this.speedSelect) {
              case SPEED_ZERO:
                this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_00_X);
                break;
              case SPEED_ONE:
                this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_25_X);
                break;
              case SPEED_TWO:
                this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_75_X);
                break;
              case SPEED_THREE:
                this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_2_00_X);
                break;
            }
          }
          callback(this.avPlayer);
          break;
        case 'playing': // play成功调用后触发该状态机上报
          console.info(`${this.tag}: setAVPlayerCallback AVPlayer state playing called.`);
          if (this.count !== 0) {
            if (this.intervalID != -1) {
              clearInterval(this.intervalID)
            }
            this.intervalID = setInterval(() => { // 更新当前时间
              AppStorage.setOrCreate('durationTime', this.durationTime);
              AppStorage.setOrCreate('currentTime', this.currentTime);
            }, 100);
            let eventDataTrue: emitter.EventData = {
              data: {
                'flag': true
              }
            };
            let innerEventTrue: emitter.InnerEvent = {
              eventId: 2,
              priority: emitter.EventPriority.HIGH
            };
            emitter.emit(innerEventTrue, eventDataTrue);
          } else {
            setTimeout(() => {
              console.info('AVPlayer playing wait to pause');
              this.avPlayer?.pause(); // 播放3s后调用暂停接口暂停播放。
            }, 3000);
          }
          this.count++;
          break;
        case 'completed': // 播放结束后触发该状态机上报
          console.info(`${this.tag}: setAVPlayerCallback AVPlayer state completed called.`);
          let eventDataFalse: emitter.EventData = {
            data: {
              'flag': false
            }
          };
          let innerEvent: emitter.InnerEvent = {
            eventId: 1,
            priority: emitter.EventPriority.HIGH
          };
          emitter.emit(innerEvent, eventDataFalse);
          if (this.intervalID != -1) {
            clearInterval(this.intervalID)
          }
          this.avPlayer.off('bufferingUpdate')
          AppStorage.setOrCreate('currentTime', this.durationTime);
          break;
        case 'released':
          console.info(`${this.tag}: setAVPlayerCallback released called.`);
          break
        case 'stopped':
          console.info(`${this.tag}: setAVPlayerCallback AVPlayer state stopped called.`);
          break
        case 'error':
          console.error(`${this.tag}: setAVPlayerCallback AVPlayer state error called.`);
          break
        case 'paused':
          console.info(`${this.tag}: setAVPlayerCallback AVPlayer state paused called.`);
          setTimeout(() => {
            console.info('AVPlayer paused wait to play again');
            this.avPlayer?.play(); // 暂停3s后再次调用播放接口开始播放。
          }, 3000);
          break
        default:
          console.info(`${this.tag}: setAVPlayerCallback AVPlayer state unknown called.`);
          break;
      }
    });
    // 时间上报监听函数
    this.avPlayer.on('timeUpdate', (time: number) => {
      this.currentTime = time;
    });
  }

  aboutToAppear() {
    this.windowWidth = display.getDefaultDisplaySync().width;
    this.windowHeight = display.getDefaultDisplaySync().height;
    this.surfaceW = this.windowWidth * SURFACE_W;
    this.surfaceH = this.surfaceW / SURFACE_H;
    this.isPaused = true;
    this.context = getContext(this) as common.UIAbilityContext;
  }

  aboutToDisappear() {
    if (this.avPlayer == null) {
      console.info(`${this.tag}: avPlayer has not init aboutToDisappear`);
      return;
    }
    this.avPlayer.release((err) => {
      if (err == null) {
        console.info(`${this.tag}: videoRelease release success`);
      } else {
        console.error(`${this.tag}: videoRelease release failed, error message is = ${JSON.stringify(err.message)}`);
      }
    });
    emitter.off(innerEventFalse.eventId);
  }

  onPageHide() {
    this.avPause();
    this.isPaused = false;
  }

  onPageShow() {

    //const params = router.getParams();
    //this.fileName = params.toString();
    console.log("myData2",this.myData);
    this.fileName = this.myData+".mp3";
    console.log("myData2",this.fileName);


  emitter.on(innerEventTrue, (res: emitter.EventData) => {
    if (res.data) {
      this.isPaused = res.data.flag;
      this.XComponentFlag = res.data.flag;
    }
  });
  emitter.on(innerEventFalse, (res: emitter.EventData) => {
    if (res.data) {
      this.isPaused = res.data.flag;
    }
  });
  emitter.on(innerEventWH, (res: emitter.EventData) => {
    if (res.data) {
      this.windowWidth = res.data.width;
      this.windowHeight = res.data.height;
      this.setVideoWH();
    }
  });
}

setVideoWH(): void {
  if (this.percent >= 1) { // 横向视频
    this.surfaceW = Math.round(this.windowWidth * PROPORTION);
    this.surfaceH = Math.round(this.surfaceW / this.percent);
  } else { // 纵向视频
    this.surfaceH = Math.round(this.windowHeight * PROPORTION);
    this.surfaceW = Math.round(this.surfaceH * this.percent);
  }
}

@Builder
CoverXComponent() {
  XComponent({
    // 装载视频容器
    id: 'xComponent',
    type: XComponentType.SURFACE,
    controller: this.xComponentController
  })
    .id('VideoView')
    .visibility(this.XComponentFlag ? Visibility.Visible : Visibility.Hidden)
    .onLoad(() => {
      this.surfaceId = this.xComponentController.getXComponentSurfaceId();
      this.avSetupAudio();
    })
    .height(`${this.surfaceH}px`)
    .width(`${this.surfaceW}px`)
}

build() {
  Column() {
    Stack() {
      Column() {
        this.CoverXComponent()
      }
      .align(Alignment.TopStart)
      .margin({ top: 80 })
      .id('VideoView')
      .justifyContent(FlexAlign.Center)
      Row(){
        Image($r('app.media.vinyl'))
          .width('100%')
          .height('40%')
      }

      Text()
        .height(`${this.surfaceH}px`)
        .width(`${this.surfaceW}px`)
        .margin({ top: 80 })
        .backgroundColor(Color.Black)
        .opacity($r('app.float.size_zero_five'))
        .visibility(this.isSwiping ? Visibility.Visible : Visibility.Hidden)

      Row() {
        Text(this.timeConvert(this.currentTime))
          .id("currentTime")
          .fontSize($r('app.float.size_24'))
          .opacity($r('app.float.size_1'))
          .fontColor($r("app.color.slider_selected"))
        Text("/" + this.timeConvert(this.durationTime))
          .id("durationTime")
          .fontSize($r('app.float.size_24'))
          .opacity($r('app.float.size_1'))
          .fontColor(Color.White)
      }
      .margin({ top: 80 })
      .visibility(this.isSwiping ? Visibility.Visible : Visibility.Hidden)

      Column() {

        Blank()

        Column() {
          // 进度条
          Row() {
            Row() {
              // 播放、暂停键
              Image(this.isPaused ? $r("app.media.ic_video_play") : $r("app.media.ic_video_pause"))// 暂停/播放
                .id(this.isPaused ? 'pause' : 'play')
                .width($r('app.float.size_40'))
                .height($r('app.float.size_40'))
                .onClick(() => {
                  if (this.isPaused) {
                    this.avPause();
                    this.isPaused = false;
                  } else {
                    this.avPlay();
                    this.isPaused = true;
                  }
                })
              // 左侧时间
              Text(this.timeConvert(this.currentTime))
                .id("currentTimeText")
                .fontColor(Color.White)
                .textAlign(TextAlign.End)
                .fontWeight(FontWeight.Regular)
                .margin({ left: $r('app.float.size_10') })
            }

            // 进度条
            Row() {
              Slider({
                value: this.currentTime,
                min: 0,
                max: this.durationTime,
                style: SliderStyle.OutSet
              })
                .id('Slider')
                .blockColor(Color.White)
                .trackColor(Color.Gray)
                .selectedColor($r("app.color.slider_selected"))
                .showTips(false)
                .onChange((value: number, mode: SliderChangeMode) => {
                  if (this.seekTime !== value) {
                    this.seekTime = value;
                    this.avSeek(Number.parseInt(value.toFixed(0)), mode);
                  }
                })
            }
            .layoutWeight(1)

            Row() {
              // 右侧时间
              Text(this.timeConvert(this.durationTime))
                .id("durationTimeText")
                .fontColor(Color.White)
                .fontWeight(FontWeight.Regular)

              // 倍速按钮
              Button(this.speedName, { type: ButtonType.Normal })
                .border({ width: $r('app.float.size_1'), color: Color.White })
                .width(75)
                .height($r('app.float.size_40'))
                .fontSize($r('app.float.size_15'))
                .borderRadius($r('app.float.size_24'))
                .fontColor(Color.White)
                .backgroundColor(Color.Black)
                .opacity($r('app.float.size_1'))
                .margin({ left: $r('app.float.size_10') })
                .id('Speed')
                .onClick(() => {
                  this.speedIndex = (this.speedIndex + 1) % SPEED_COUNT;
                  this.speedSelect = this.speedIndex;
                  this.speedName = this.speedList[this.speedIndex];
                  if(!this.avPlayer) return;
                  switch (this.speedSelect) {
                    case 0:
                      this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_00_X);
                      break;
                    case 1:
                      this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_25_X);
                      break;
                    case 2:
                      this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_75_X);
                      break;
                    case 3:
                      this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_2_00_X);
                      break;
                  }
                })
            }
          }
          .justifyContent(FlexAlign.Center)
          .padding({ left: $r('app.float.size_25'), right: $r('app.float.size_30') })
          .width('100%')
        }
        .width('100%')
        .justifyContent(FlexAlign.Center)
      }
      .width('100%')
      .height('100%')
    }
    .backgroundColor(Color.Black)
    .height('90%')
    .width('100%')

    Row() {
      Text(this.fileName)
        .fontSize($r('app.float.size_20'))
        .fontColor(Color.White)
        .opacity($r('app.float.size_zero_six'))
        .fontWeight(FontWeight.Regular)
        .textAlign(TextAlign.Center)
    }
    Row() {
      Text("")
        .fontSize($r('app.float.size_20'))
        .fontColor(Color.White)
        .opacity($r('app.float.size_zero_six'))
        .fontWeight(FontWeight.Regular)
        .textAlign(TextAlign.Center)
    }
  }.backgroundColor(Color.Black)
  .height('100%')
  .width('100%')
}
}

2.3 App.ets文件,通过LocalStorage实现组件间数据共享

复制代码
// App.ets
const storage = new LocalStorage();
export default storage;

三、显示效果

相关推荐
巴里巴气2 小时前
zookeeper基本概念介绍
linux·分布式·zookeeper
codu4u13143 小时前
Maven中的bom和父依赖
java·linux·maven
lixzest5 小时前
Linux 中,命令查看系统版本和内核信息
linux·运维·服务器
朱小弟cs65 小时前
Orange的运维学习日记--16.Linux时间管理
linux·运维·学习
chen_note5 小时前
LAMP及其环境的部署搭建
linux·运维·mysql·php·apache·lamp·phpmyadmin
夕泠爱吃糖5 小时前
Linux 操作系统
linux·运维·服务器
zhanshuo6 小时前
鸿蒙开发实战:分布式数据一致性机制详解 + 示例代码
harmonyos
zhanshuo6 小时前
分布式到底有啥用?鸿蒙在工业场景的三个实战告诉你答案
harmonyos
Linux技术支持工程师6 小时前
二十八、【Linux系统域名解析】DNS安装、子域授权、缓存DNS、分离解析、多域名解析
linux·运维·服务器·缓存·centos
jim写博客7 小时前
linux进程概念(三)进程状态
linux·运维·服务器