diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/.gitignore b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/.gitignore @@ -0,0 +1,12 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/app.json5 b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..acaf7197361d6c190ceef46a4e04113a4cad1559 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 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. + */ +{ + "app": { + "bundleName": "com.samples.AVPlayerArkTSStreamingMedia", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/element/string.json b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..702add974b7a0582ed7670109b1f42dfeb1f7166 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "AVPlayerArkTSStreamingMedia" + } + ] +} diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/media/background.png b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/media/background.png differ diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/media/foreground.png b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/media/foreground.png differ diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/media/layered_image.json b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/README.md b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/README.md new file mode 100644 index 0000000000000000000000000000000000000000..01ebff0b997a8203d689f0e2a8c0f8c005eac5cb --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/README.md @@ -0,0 +1,66 @@ +# AVPlayerArkTSStreamingMedia + +## 介绍 + +本示例为媒体->Media Kit(媒体服务)->[使用AVPlayer播放流媒体(ArkTS)](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/media/media/streaming-media-playback-development-guide.md)的配套示例工程。 + +本示例展示了如何使用AVPlayer组件完整地播放一个流媒体视频。 + +## 效果预览 + +| 播放效果 | +| -------------------------------------------- | + + + +## 工程目录 + +``` +AVPlayerArkTSStreamingMedia +entry/src/main/ets/ +└── pages + └── Index.ets (播放界面) +entry/src/main/resources/ +├── base +│ ├── element +│ │ ├── color.json +│ │ ├── float.json +│ │ └── string.json +│ └── media +│ ├── ic_video_play.svg (播放键图片资源) +│ └── ic_video_pause.svg (暂停键图片资源) +└── rawfile + └── test1.mp4 (视频资源) +entry/src/ohosTest/ets/ +└── test + ├── Ability.test.ets (UI测试代码) + └── List.test.ets (测试套件列表) +``` + +## 相关权限 + +不涉及 + +## 依赖 + +不涉及 + +## 约束和限制 + +1. 本示例支持标准系统上运行,支持设备:RK3568; + +2. 本示例支持API15版本SDK,版本号:5.0.3.135; + +3. 本示例已支持使DevEco Studio 5.0.3 Release (构建版本:5.0.8.300,构建 2025年3月19日)编译运行 + +## 下载 + +如需单独下载本工程,执行如下命令: + +``` +git init +git config core.sparsecheckout true +echo code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/ > .git/info/sparse-checkout +git remote add origin OpenHarmony/applications_app_samples +git pull origin master +``` \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/build-profile.json5 b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d5c009e8f6cf5e277b47a6bf2df2250f05ca4ddc --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/build-profile.json5 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 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. + */ +{ + "app": { + "products": [ + { + "name": "default", + "signingConfig": "default", + "compileSdkVersion": 15, + "targetSdkVersion": 15, + "compatibleSdkVersion": 15, + "runtimeOS": "OpenHarmony" + } + ], + "buildModeSet": [ + { + "name": "debug" + }, + { + "name": "release" + } + ], + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/.gitignore b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/.gitignore @@ -0,0 +1,6 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/build-profile.json5 b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..982dbb524bd63408e05cfbed7204dd87a31dd681 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/build-profile.json5 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 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. + */ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/hvigorfile.ts b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..8774588471ede4c1563f09d9a1d22f764bb1fd9e --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 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 { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/obfuscation-rules.txt b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/oh-package.json5 b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..10cda399b0aec3099b257299a57d284393e4e55a --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 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. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": {} +} + diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/ets/entryability/EntryAbility.ets b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..843c7f0c1f7b9a460e3dbbd2689e5b34016027d1 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,58 @@ +/* + * Copyright (c) 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 { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ce6449f0e91914e73d4502c9f2e8e9a395ea4b1 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,30 @@ +/* + * Copyright (c) 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 { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/ets/pages/Index.ets b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..7423d20b7c7b75388802311915b9529abea6e83a --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,611 @@ +/* + * 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 { BusinessError } from '@kit.BasicServicesKit'; + +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 +@Component +struct Index { + 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; + public videoTrackIndex: number = 0; + public bitrate: number = 0; + + @State title: Resource = $r('app.string.EntryAbility_label'); + @State fileName: string = 'test1.mp4'; + @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 { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve(true) + }, ms) + }) + } + + async avSetupStreaminMediaVideo() { + if (this.context == undefined) return; + // 创建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); + }); + + // 情况一:HTTP视频播放 + this.avPlayer.url = "http://media.iyuns.top:1000/http/720p_1m.mp4"; + + // 情况二:HLS视频播放 + // this.avPlayer.url = "http://media.iyuns.top:1000/720-270-480.m3u8"; + + // 情况三:DASH视频播放 + // this.avPlayer.url = "http://media.iyuns.top:1000/dash/720p/720-1/720-1.mpd"; + + // 情况四:通过setMediaSource设置自定义头域及播放优选参数实现初始播放参数设置,以流媒体HTTP点播为例 + /* + let mediaSource : media.MediaSource = media.createMediaSourceWithUrl("http://media.iyuns.top:1000/http/720p_1m.mp4", {"":""}); + // 设置播放策略,设置为缓冲区数据为20s + let playbackStrategy : media.PlaybackStrategy = {preferredBufferDuration: 20}; + // 为avPlayer设置媒体来源和播放策略 + this.avPlayer.setMediaSource(mediaSource, playbackStrategy); + * */ + + // 情况五:HLS切码率 + /* + this.avPlayer.url = "https://upftimae.dailyworkout.cn/videos/course/c800f81a209b5ee7891f1128ed301db/4/master.m3u8"; + let bitrate: number = 0; + // 监听当前HLS协议流可用的码率 + this.avPlayer.on('availableBitrates', (bitrates: Array) => { + console.info('availableBitrates called, and availableBitrates length is: ' + bitrates.length); + this.bitrate = bitrates[0]; // 保存需要切换的码率 + }) + // 监听码率设置是否生效 + this.avPlayer.on('bitrateDone', (bitrate: number) => { + console.info('bitrateDone called, and bitrate value is: ' + bitrate); + }) + * */ + + // 情况六:DASH切换音视频轨道 + /* + this.avPlayer.url = "http://poster-inland.hwcloudtest.cn/AiMaxEngine/ProductionEnvVideo/DASH_SDR_MultiAudio_MultiSubtitle_yinHeHuWeiDui3/DASH_SDR_MultiAudio_MultiSubtitle_yinHeHuWeiDui3.mpd"; + // + this.avPlayer.getTrackDescription((error: BusinessError, arrList: Array) => { + if (arrList != null) { + for (let i = 0; i < arrList.length; i++) { + let propertyIndex: Object = arrList[i][media.MediaDescriptionKey.MD_KEY_TRACK_INDEX]; + let propertyType: Object = arrList[i][media.MediaDescriptionKey.MD_KEY_TRACK_TYPE]; + let propertyWidth: Object = arrList[i][media.MediaDescriptionKey.MD_KEY_WIDTH]; + let propertyHeight: Object = arrList[i][media.MediaDescriptionKey.MD_KEY_HEIGHT]; + if (propertyType == media.MediaType.MEDIA_TYPE_VID && propertyWidth == 1920 && propertyHeight == 1080) { + this.videoTrackIndex = parseInt(propertyIndex.toString()); // 获取1080p视频轨道索引。 + } + } + } else { + console.error(`getTrackDescription fail, error:${error}`); + } + }); + * */ + } + + // HLS切换码率 + changeBitrate(bitrate: number) { + if (this.avPlayer == null) { + return; + } + // 设置播放码率 + try { + this.avPlayer.setBitrate(bitrate); + } catch (error) { + console.error(`${this.tag}: setBitrate failed, error message is = ${JSON.stringify(error.message)}`); + } + } + + // DASH切换音视频轨道 + changeTrack(track: number) { + if (this.avPlayer == null) { + return; + } + // 切换至目标视频轨道 + try { + this.avPlayer.selectTrack(track); + } catch (error) { + console.error(`${this.tag}: selectTrack failed, error message is = ${JSON.stringify(error.message)}`); + } + // 取消选择目标视频轨道 + /* + try { + this.avPlayer.deselectTrack(track); + } catch (error) { + console.error(`${this.tag}: deselectTrack failed, error message is = ${JSON.stringify(error.message)}`); + } + * */ + } + + 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 { + 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 { + // 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.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); + 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.`); + 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() { + 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.avSetupStreaminMediaVideo(); + }) + .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) + + 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.title) + .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%') + } +} diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/module.json5 b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c75d702e2d350523978ecaf801c22762ce7d40c0 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/module.json5 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 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. + */ +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/element/color.json b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..419aa49d53413d68acdd73edc8d2b80d01ef60e9 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/element/color.json @@ -0,0 +1,24 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + }, + { + "name": "slider_selected", + "value": "#007DFF" + }, + { + "name": "speed_dialog", + "value": "#33bab4b4" + }, + { + "name": "video_play", + "value": "#333333" + }, + { + "name": "video_play_selected", + "value": "#5c5c5c" + } + ] +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/element/float.json b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..09ea9cdfd57c520f94abc39a9ecb6cdecee137b0 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/element/float.json @@ -0,0 +1,92 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + }, + { + "name": "size_zero_five", + "value": "0.5" + }, + { + "name": "size_zero_six", + "value": "0.6" + }, + { + "name": "size_zero", + "value": "0" + }, + { + "name": "size_1", + "value": "1" + }, + { + "name": "size_5", + "value": "5" + }, + { + "name": "size_10", + "value": "10" + }, + { + "name": "size_12", + "value": "12" + }, + { + "name": "size_15", + "value": "15" + }, + { + "name": "size_16", + "value": "16" + }, + { + "name": "size_18", + "value": "18" + }, + { + "name": "size_20", + "value": "20" + }, + { + "name": "size_down_20", + "value": "-20" + }, + { + "name": "size_24", + "value": "24" + }, + { + "name": "size_25", + "value": "25" + }, + { + "name": "size_30", + "value": "30" + }, + { + "name": "size_32", + "value": "32" + }, + { + "name": "size_35", + "value": "35" + }, + { + "name": "size_40", + "value": "40" + }, + { + "name": "size_45", + "value": "45" + }, + { + "name": "size_48", + "value": "48" + }, + { + "name": "size_50", + "value": "50" + } + ] +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/element/string.json b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..e546a4d960e8becdaf2fe43cfe102d901a08f7f5 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/element/string.json @@ -0,0 +1,56 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "ArkTS播放流媒体示例" + }, + { + "name": "video_speed_1_0X", + "value": "1.0X" + }, + { + "name": "video_speed_1_25X", + "value": "1.25X" + }, + { + "name": "video_speed_1_75X", + "value": "1.75X" + }, + { + "name": "video_speed_2_0X", + "value": "2.0X" + }, + { + "name": "video_warn", + "value": "退出程序,请检查网络是否连接或可用!" + }, + { + "name": "dialog_play_speed", + "value": "播放倍速" + }, + { + "name": "dialog_cancel", + "value": "取消" + }, + { + "name": "playing", + "value": "当前播放" + }, + { + "name": "reason", + "value": "video" + }, + { + "name": "playing_now", + "value": "立即播放" + } + ] +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/background.png b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/background.png differ diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/foreground.png b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/foreground.png differ diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/ic_video_pause.svg b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/ic_video_pause.svg new file mode 100644 index 0000000000000000000000000000000000000000..b18a4a3d00cf2f80fe90c55faef56b39ed485a1b --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/ic_video_pause.svg @@ -0,0 +1,13 @@ + + + Public/ic_public_play + + + + + + + + + + \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/ic_video_play.svg b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/ic_video_play.svg new file mode 100644 index 0000000000000000000000000000000000000000..675bf7f87b66ed5011191b77c1f3f678625be68a --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/ic_video_play.svg @@ -0,0 +1,13 @@ + + + Public/ic_public_pause + + + + + + + + + + \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/layered_image.json b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/startIcon.png b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/media/startIcon.png differ diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/profile/backup_config.json b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/profile/main_pages.json b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/dark/element/color.json b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/rawfile/test1.mp4 b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/rawfile/test1.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..417649af1c7deea97e41abac156462e99e17b78d --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/main/resources/rawfile/test1.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b92bd019ee0b002b8f7f665e75401cc45190c94e396423494b53f25800354f9 +size 21780300 diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/mock/mock-config.json5 b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..323d1d611fecf4ecb751976e3a71500b3712a445 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/mock/mock-config.json5 @@ -0,0 +1,16 @@ +/* + * Copyright (c) 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. + */ +{ +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/ohosTest/ets/test/Ability.test.ets b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..c78d8926c4ae08670a763eb341b4fccc42d0954a --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,117 @@ +/* + * Copyright (c) 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 { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; +import { Driver, ON } from '@ohos.UiTest'; +import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; + +export default function abilityTest() { + const TAG = '[Sample_AVPlayerArkTS]'; + const DOMAIN = 0xF811; + const driver = Driver.create(); + const abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); + const bundleName = AbilityDelegatorRegistry.getArguments().bundleName; + + describe('ActsAbilityTest', () => { + + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + + + /** + * 打开应用 + */ + it('StartAbility_001', 0, async (done: Function) => { + console.info(TAG, 'StartAbility_001 begin'); + + try { + await abilityDelegator.startAbility({ + bundleName: bundleName, + abilityName: 'EntryAbility' + }); + } catch (exception) { + hilog.error(DOMAIN, TAG, `StartAbility_001 exception = ${JSON.stringify(exception)}`); + expect().assertFail(); + } + await driver.delayMs(3000); + done(); + console.info(TAG, 'StartAbility_001 end'); + }) + + /** + * 播放、暂停、拖进度条 + */ + it('Slider_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, 'Slider_001 begin'); + + // 点播放 + await driver.delayMs(2000); + await driver.assertComponentExist(ON.type('Image')); + let stack = await driver.findComponent(ON.type('Image')); + + // 暂停 + await stack.click(); + await driver.delayMs(3000); + + // 滑动滑块 + await driver.assertComponentExist(ON.id('Slider')); + let Slider = await driver.findComponent(ON.id('Slider')); + let point = await Slider.getBoundsCenter(); + await driver.drag(point.x - 50, point.y, point.x + 50, point.y, 800); + await driver.delayMs(1000); + + // 播放 + await stack.click(); + await driver.delayMs(1000); + + done(); + hilog.info(DOMAIN, TAG, 'Slider_001 end'); + }) + + /** + * 暂停并退出 + */ + it('Exit_001', 0, async (done: Function) => { + hilog.info(DOMAIN, TAG, 'Exit_001 begin'); + + // 暂停 + await driver.delayMs(8000); + await driver.assertComponentExist(ON.type('Image')); + let stack = await driver.findComponent(ON.type('Image')); + await stack.click(); + await driver.delayMs(2000); + + done(); + hilog.info(DOMAIN, TAG, 'Exit_001 end'); + }) + }) +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/ohosTest/ets/test/List.test.ets b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..c64e0b06938d246ce044186d4b2d02b500a89e14 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 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 abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/ohosTest/module.json5 b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..f6bdce9946cb02c0385e5a8836c133c93945013d --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/ohosTest/module.json5 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 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. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/test/List.test.ets b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..a60c87c5cbb0badf7c3fd8975034590e6fafa992 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/test/List.test.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 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 localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/test/LocalUnit.test.ets b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..321f9be81fd772a5af6e71dafebf7ed905a6ccff --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,39 @@ +/* + * Copyright (c) 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + }); +} \ No newline at end of file diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/hvigor/hvigor-config.json5 b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4d435603637cbbfe92ac9865537a0c1051810bb1 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/hvigor/hvigor-config.json5 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 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. + */ +{ + "modelVersion": "5.0.5", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/hvigorfile.ts b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..6b365cacd0191d3b1178eb6b9807b1ae0add6271 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/hvigorfile.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 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 { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/oh-package.json5 b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..38abfd099681aeb547cf83a4966111dd5f4f6d13 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 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. + */ +{ + "modelVersion": "5.0.5", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.21", + "@ohos/hamock": "1.0.0" + } +} diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/ohosTest.md b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..376d0be2ce79a2d8ec6a625ecfeb08c2fe038aa8 --- /dev/null +++ b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/ohosTest.md @@ -0,0 +1,10 @@ +# AVPlayerArkTSStreamingMedia测试用例归档 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +| ---------------- | ------------------ | -------------------- | ---------------------------- | -------- | -------- | +| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass | +| 播放功能 | 进入示例应用 | 点击播放按钮 | 成功播放资源 | 是 | Pass | +| 拖动功能 | 进入示例应用 | 点击、拖动进度条 | 成功改变播放进度 | 是 | Pass | +| 暂停功能 | 进入示例应用 | 点击移动按钮 | 成功暂停播放 | 是 | Pass | diff --git a/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/screenshots/AVPlayerArkTSStreamingMedia.jpg b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/screenshots/AVPlayerArkTSStreamingMedia.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e69aebc184f541b7ebdbd55b092bc2e44f35ce46 Binary files /dev/null and b/code/DocsSample/Media/AVPlayer/AVPlayerArkTSStreamingMedia/screenshots/AVPlayerArkTSStreamingMedia.jpg differ