diff --git a/Media/Audio_OH_ETS/AppScope/app.json5 b/Media/Audio_OH_ETS/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..698f6199c92dca464fb7f7a37de4a9b1d6634b6c
--- /dev/null
+++ b/Media/Audio_OH_ETS/AppScope/app.json5
@@ -0,0 +1,13 @@
+{
+ "app": {
+ "bundleName": "com.huawei.cookbook",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:app_icon",
+ "label": "$string:app_name",
+ "distributedNotificationEnabled": true,
+ "minAPIVersion": 9,
+ "targetAPIVersion": 9
+ }
+}
diff --git a/Media/Audio_OH_ETS/AppScope/resources/base/element/string.json b/Media/Audio_OH_ETS/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..84fe5ad9c9a438166d29f7fa7670a3a18e3b1ee3
--- /dev/null
+++ b/Media/Audio_OH_ETS/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "AudioEtsWGR"
+ }
+ ]
+}
diff --git a/Media/Audio_OH_ETS/AppScope/resources/base/media/app_icon.png b/Media/Audio_OH_ETS/AppScope/resources/base/media/app_icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/Media/Audio_OH_ETS/AppScope/resources/base/media/app_icon.png differ
diff --git a/Media/Audio_OH_ETS/LICENSE b/Media/Audio_OH_ETS/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..80576ef141485b36eea4aebf25af97020bc2de44
--- /dev/null
+++ b/Media/Audio_OH_ETS/LICENSE
@@ -0,0 +1,78 @@
+ Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved.
+
+ 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.
+
+Apache License, Version 2.0
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+1.You must give any other recipients of the Work or Derivative Works a copy of this License; and
+2.You must cause any modified files to carry prominent notices stating that You changed the files; and
+3.You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+4.If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/README.md b/Media/Audio_OH_ETS/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..dbf6a673c4ffca5246b91630800fe8cf97d93593
--- /dev/null
+++ b/Media/Audio_OH_ETS/README.md
@@ -0,0 +1,306 @@
+# 介绍
+
+本教程为您展示如何使用OpenHarmony的媒体组件AudioRecorder收录当前音频,并使用AudioPlayer播放已收录的音频。本应用包含一个页面,控制录音结束后展示录音文件列表。效果图如下:
+
+**图 1**
+
+
+
+
+
+# 搭建OpenHarmony环境
+
+完成本篇Codelab我们首先要完成开发环境的搭建,本示例以**RK3568**开发板为例,参照以下步骤进行:
+
+1. [获取OpenHarmony系统版本](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/get-code/sourcecode-acquire.md#%E8%8E%B7%E5%8F%96%E6%96%B9%E5%BC%8F3%E4%BB%8E%E9%95%9C%E5%83%8F%E7%AB%99%E7%82%B9%E8%8E%B7%E5%8F%96):标准系统解决方案(二进制)。
+
+ 以3.1版本为例:
+
+ 
+
+2. 搭建烧录环境。
+ 1. [完成DevEco Device Tool的安装](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/quickstart-standard-env-setup.md)
+ 2. 完成RK3568开发板的烧录
+
+ - [DevEco Device Tool编译源码烧录](https://device.harmonyos.com/cn/docs/documentation/guide/ide-rk3568-upload-0000001239220669)
+ - [每日构建版本烧录](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/quickstart-standard-running-rk3568-burn.md)
+
+3. 搭建开发环境。
+
+ 1. 开始前请参考[下载与安装软件](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/software_install-0000001053582415)、[配置开发环境](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/configuring-openharmony-sdk.md),完成DevEco Studio的安装和开发环境配置。
+ 2. 开发环境配置完成后,请参考[使用工程向导](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/use-wizard-to-create-project.md)创建工程,选择JS或者eTS语言开发、“Application”为例,模板选择“\[Standard\]Empty Ability”。
+ 3. 工程创建完成后,可参考下面章节进行代码编写,使用真机进行调测:
+
+ - [配置OpenHarmony应用签名信息](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/configuring-openharmony-app-signature.md)
+ - [hap包安装指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/installing-openharmony-app.md)
+ - 工程示例:
+
+ 
+
+
+
+ # 代码结构解读
+
+ 
+
+ - resources:文件夹存放一些公共的资源,比如图片。
+
+ - pages:用于存放所有页面的目录。
+ - index.ets:录音页面文件。
+
+
+ - util:用于存放常用工具类的目录。
+ - DateTimeUtils.ets:用于处理日期格式转化的工具类。
+ - DataTypeUtils.ets:用于处理数据格式的工具类。
+ - SysPermissionUtils.ets:用于申请系统权限的工具类
+
+
+ - model:用于存放项目中使用到的能力模块。
+ - AudioPlay.ets:用于音频播放模块接口。
+
+ - AudioRecord.ets:用于音频录制模块接口。
+ - MediaLibOperator.ets:用于操作媒体库模块接口文件
+ - module.json5:配置文件。
+
+
+
+# 音频录制
+
+点击“开始录制”按钮,开始收集音频流,在代码配置的uri地址保存录音文件。
+
+1. 初始化自定义音频录制AudioRecord模块,在构造方法中实例化AudioRecorder,并在其生命周期中处理后续逻辑和回调Recorder状态。
+
+ ```
+ initAudioRecorder() {
+ this.recorder = media.createAudioRecorder();
+ this.setOperateListener();
+ this.setStatusListener();
+ }
+
+ setOperateListener() {
+ this.recorder.on('reset', () => {
+ this.currentState = RecordState.RESET;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.RESET);
+ }
+ });
+ this.recorder.on('release', () => {
+ this.currentState = RecordState.RELEASE;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.RELEASE);
+ }
+ });
+ this.recorder.on('error', (err) => {
+ console.info('AudioRecorder error callback,err is ' + JSON.stringify(err))
+ this.currentState = RecordState.ERROR;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.ERROR, err);
+ }
+ });
+ }
+
+ setStatusListener() {
+ this.recorder.on('prepare', () => {
+ this.recorder.start();
+ this.currentState = RecordState.PREPARE;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.PREPARE);
+ }
+ });
+ this.recorder.on('start', () => {
+ this.currentState = RecordState.START;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.START, this.curRecordAsset);
+ }
+ });
+ this.recorder.on('pause', () => {
+ this.currentState = RecordState.PAUSE;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.PAUSE);
+ }
+ });
+ this.recorder.on('resume', () => {
+ this.currentState = RecordState.RESUME;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.RESUME);
+ }
+ });
+ this.recorder.on('stop', () => {
+ this.currentState = RecordState.STOP;
+ this.mediaLibOperator.closeOperationChannel()
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.STOP);
+ }
+ });
+ }
+ ```
+
+2. 监听AudioRecorder状态。
+
+ ```
+ this.recorder.setOnStatusChangedListener((state, extra) => {
+ switch (state) {
+ case RecordState.START:
+ this.curRecordInfo = extra
+ break
+ case RecordState.STOP:
+ this.audioRecordList.unshift(this.curRecordInfo)
+ break
+ }
+ })
+ ```
+
+3. 开始/停止录制。
+
+ ```
+ if (event.type === TouchType.Down) {
+ this.isCaptureBtnPress = true
+ } else if (event.type === TouchType.Up) {
+ this.isCaptureBtnPress = false
+ if (this.recorder.isRecording()) {
+ this.captureBtnSrc = $r('app.media.ic_record')
+ this.recorder.stop()
+ } else {
+ this.captureBtnSrc = $r('app.media.ic_record_stop')
+ this.recorder.start()
+ }
+ }
+ ```
+
+4. 录制成功后,刷新列表界面。
+
+ ```
+ this.audioRecordList.unshift(this.curRecordInfo)
+ ```
+
+5. 释放AudioRecorder。
+
+ ```
+ this.recorder.release()
+ ```
+
+
+
+# 音频播放
+
+选择录音列表项,开始播放音频流,当前所有录音均指向同一个文件。
+
+1. 初始化自定义音频录制AudioPlay模块,在构造方法中实例化AudioPlayer,并在其生命周期中处理后续逻辑和回调Player状态。
+
+ ```
+ initAudioPlayer() {
+ this.#player = media.createAudioPlayer();
+ this.setOperateListener();
+ this.setStatusListener();
+ }
+
+ setOperateListener() {
+ this.#player.on('finish', () => {
+ this.#currentState = AudioPlayerState.FINISH;
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.FINISH);
+ }
+ });
+ this.#player.on('timeUpdate', (seekTime, action) => {
+ this.#currentTimeMs = parseInt(seekTime);
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.TIME_UPDATE, JSON.stringify(action));
+ }
+ });
+ this.#player.on('volumeChange', () => {
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.VOLUME_CHANGE);
+ }
+ });
+ }
+
+ setStatusListener() {
+ this.#player.on('dataLoad', () => {
+ this.#currentState = AudioPlayerState.LOAD;
+ if (this.#isAutoPlay) {
+ this.#player.play();
+ }
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.LOAD);
+ }
+ });
+ this.#player.on('play', () => {
+ this.#currentState = AudioPlayerState.PLAY;
+ if (this.#currentTimeMs > 0) {
+ this.seek(this.#currentTimeMs);
+ }
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.PLAY);
+ }
+ });
+ this.#player.on('pause', () => {
+ this.#currentState = AudioPlayerState.PAUSE;
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.PAUSE);
+ }
+ });
+ this.#player.on('stop', () => {
+ this.#currentState = AudioPlayerState.STOP;
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.STOP);
+ }
+ });
+ this.#player.on('error', (err) => {
+ this.#currentState = AudioPlayerState.ERROR;
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.ERROR, err);
+ }
+ });
+ }
+ ```
+
+2. 监听AudioPlayer状态。
+
+ ```
+ this.player.setOnStatusChangedListener((state, extra) => {
+ switch (state) {
+ case AudioPlayerState.FINISH:
+ this.mediaLibOperator.closeOperationChannel()
+ break
+ }
+ })
+ ```
+
+3. 音频播放。
+
+ ```
+ if (this.recorder.isRecording()) {
+ prompt.showToast({
+ message: 'Please stop record first!',
+ duration: 3000,
+ bottom: 100
+ })
+ return;
+ }
+ this.player.stop()
+ this.mediaLibOperator.openAssetOperationChannel(item.id).then((operationAsset) => {
+ console.info('cwq getAssetFd success,fd is ' + operationAsset.operationId.toString())
+ this.player.play("fd://" + operationAsset.operationId.toString(), 0, true);
+ })
+ ```
+
+4. 释放AudioPlayer.
+
+ ```
+ this.player.release()
+ ```
+
+
+
+# 恭喜你
+
+目前您已经成功完成了本篇Codelab并且学到了:
+
+- 如何使用AudioRecorder录制音频。
+- 如何使用AudioPlayer播放音频。
+
+
+
+# 参考
+
+gitee:JS音频录制应用
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/build-profile.json5 b/Media/Audio_OH_ETS/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..4b93629437d7e10de7e4db6e642f470519c11e6d
--- /dev/null
+++ b/Media/Audio_OH_ETS/build-profile.json5
@@ -0,0 +1,62 @@
+{
+ "app": {
+ "signingConfigs": [
+ {
+ "name": "debug",
+
+ "material": {
+ storeFile: 'D:\\Harmony\\openHarmony\\sign\\openHos\\openhos.p12',
+
+ //本地keystore
+
+ storePassword: "0000001815EE6158E56D4802F51B86223E4CCDC85FBAC269F04D329D43AC9AB5739D68248EE1AA44",
+
+ //生成本地keystore时的-storepass参数
+
+ keyAlias: 'hw',
+
+ //生成本地keystore时的-alias参数
+
+ keyPassword: '00000018C02B975FB9B04EC6667768B507F398DF2978D28C0CC8DFEB9D761CF49A161A0A36FAFCCE',
+
+ //keyPassword参数,pkcs12格式的keystore采用生成本地keystore时的-storepass参数
+
+ signAlg: 'SHA256withECDSA',
+
+ //生成本地keystore时的-sigalg参数
+
+ profile: 'D:\\Harmony\\openHarmony\\sign\\openHos\\openHos.p7b',
+
+ //导入调试profile
+
+ certpath: 'D:\\Harmony\\openHarmony\\sign\\openHos\\openHos.cer'
+
+ //导入调试证书
+
+ }
+ }
+ ],
+ "compileSdkVersion": 9,
+ "compatibleSdkVersion": 9,
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "debug",
+ },
+ ],
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default",
+ ],
+ },
+ ],
+ },
+ ],
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/.gitignore b/Media/Audio_OH_ETS/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..4f9a973815d0b5e49bc8547681a6b4bc7a178d12
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/.gitignore
@@ -0,0 +1,3 @@
+/node_modules
+/.preview
+/build
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/build-profile.json5 b/Media/Audio_OH_ETS/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..7dc37bb919dada5132609c409200db266559004f
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/build-profile.json5
@@ -0,0 +1,13 @@
+{
+ "apiType": 'stageMode',
+ "buildOption": {
+ },
+ "targets": [
+ {
+ "name": "default",
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/hvigorfile.js b/Media/Audio_OH_ETS/entry/hvigorfile.js
new file mode 100644
index 0000000000000000000000000000000000000000..d7720ee6a7aad5c617d1fd2f6fc8c87067bfa32c
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/hvigorfile.js
@@ -0,0 +1,2 @@
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+module.exports = require('@ohos/hvigor-ohos-plugin').hapTasks
diff --git a/Media/Audio_OH_ETS/entry/package-lock.json b/Media/Audio_OH_ETS/entry/package-lock.json
new file mode 100644
index 0000000000000000000000000000000000000000..15bc7145be1490029883067847743ea7134cf545
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/package-lock.json
@@ -0,0 +1,5 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "lockfileVersion": 1
+}
diff --git a/Media/Audio_OH_ETS/entry/package.json b/Media/Audio_OH_ETS/entry/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..c4e988f30f2ec9e3430a4d0c8f05e89fabbc2659
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "ohos": {
+ "org": "huawei",
+ "buildTool": "hvigor",
+ "directoryLevel": "module"
+ },
+ "description": "example description",
+ "repository": {},
+ "license": "ISC",
+ "dependencies": {}
+}
diff --git a/Media/Audio_OH_ETS/entry/src/main/ets/Application/AbilityStage.ts b/Media/Audio_OH_ETS/entry/src/main/ets/Application/AbilityStage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..32dfe93ccff0375201857794de902cec4d239442
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/ets/Application/AbilityStage.ts
@@ -0,0 +1,7 @@
+import AbilityStage from "@ohos.application.AbilityStage"
+
+export default class MyAbilityStage extends AbilityStage {
+ onCreate() {
+ console.log("[Demo] MyAbilityStage onCreate")
+ }
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/main/ets/MainAbility/MainAbility.ts b/Media/Audio_OH_ETS/entry/src/main/ets/MainAbility/MainAbility.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2fcd523850979edf2998174e4b5613540b9f71a5
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/ets/MainAbility/MainAbility.ts
@@ -0,0 +1,36 @@
+import Ability from '@ohos.application.Ability'
+
+export default class MainAbility extends Ability {
+ onCreate(want, launchParam) {
+ console.log("[Demo] MainAbility onCreate")
+ globalThis.abilityWant = want;
+ }
+
+ onDestroy() {
+ console.log("[Demo] MainAbility onDestroy")
+ }
+
+ onWindowStageCreate(windowStage) {
+ // Main window is created, set main page for this ability
+ console.log("[Demo] MainAbility onWindowStageCreate")
+
+ windowStage.setUIContent(this.context, "pages/index", null)
+
+ globalThis.context = this.context
+ }
+
+ onWindowStageDestroy() {
+ // Main window is destroyed, release UI related resources
+ console.log("[Demo] MainAbility onWindowStageDestroy")
+ }
+
+ onForeground() {
+ // Ability has brought to foreground
+ console.log("[Demo] MainAbility onForeground")
+ }
+
+ onBackground() {
+ // Ability has back to background
+ console.log("[Demo] MainAbility onBackground")
+ }
+};
diff --git a/Media/Audio_OH_ETS/entry/src/main/ets/model/media/AudioPlay.ets b/Media/Audio_OH_ETS/entry/src/main/ets/model/media/AudioPlay.ets
new file mode 100644
index 0000000000000000000000000000000000000000..cc6df6546d47b648482fc3a1fcb5790e587a87d7
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/ets/model/media/AudioPlay.ets
@@ -0,0 +1,181 @@
+import prompt from '@system.prompt'; /*
+ * Copyright (c) 2021 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 media from '@ohos.multimedia.media';
+import Song from '../media/been/SongInfo'
+
+let AudioPlayerState = {
+ IDLE: -1,
+ LOAD: 0,
+ PLAY: 1,
+ PAUSE: 2,
+ STOP: 3,
+ ERROR: 4,
+ FINISH: 5,
+ TIME_UPDATE: 6,
+ VOLUME_CHANGE: 7
+}
+
+export { AudioPlayerState }
+
+export class AudioPlayer {
+ playlist = new Array();
+ index = 0;
+ #player;
+ #statusChangedListener;
+ #intervalID;
+ #isAutoPlay = true;
+ #currentTimeMs = 0;
+ #currentState = AudioPlayerState.IDLE;
+ constructor() {
+ this.initAudioPlayer();
+ }
+
+ initAudioPlayer() {
+ this.#player = media.createAudioPlayer();
+ this.setOperateListener();
+ this.setStatusListener();
+ }
+
+ setOperateListener() {
+ this.#player.on('finish', () => {
+ this.#currentState = AudioPlayerState.FINISH;
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.FINISH);
+ }
+ });
+ this.#player.on('timeUpdate', (seekTime, action) => {
+ this.#currentTimeMs = parseInt(seekTime);
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.TIME_UPDATE, JSON.stringify(action));
+ }
+ });
+ this.#player.on('volumeChange', () => {
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.VOLUME_CHANGE);
+ }
+ });
+ }
+
+ setStatusListener() {
+ this.#player.on('dataLoad', () => {
+ this.#currentState = AudioPlayerState.LOAD;
+ if (this.#isAutoPlay) {
+ this.#player.play();
+ }
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.LOAD);
+ }
+ });
+ this.#player.on('play', () => {
+ this.#currentState = AudioPlayerState.PLAY;
+ if (this.#currentTimeMs > 0) {
+ this.seek(this.#currentTimeMs);
+ }
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.PLAY);
+ }
+ });
+ this.#player.on('pause', () => {
+ this.#currentState = AudioPlayerState.PAUSE;
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.PAUSE);
+ }
+ });
+ this.#player.on('stop', () => {
+ this.#currentState = AudioPlayerState.STOP;
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.STOP);
+ }
+ });
+ this.#player.on('error', (err) => {
+ this.#currentState = AudioPlayerState.ERROR;
+ if (typeof (this.#statusChangedListener) != 'undefined') {
+ this.#statusChangedListener(AudioPlayerState.ERROR, err);
+ }
+ });
+ }
+
+ release() {
+ if (typeof (this.#player) != 'undefined') {
+ this.#player.release();
+ this.#player = undefined;
+ }
+ }
+
+ addPlaySrc(name, src) {
+ let self = this;
+ self.playlist.push(new Song(name, src, 0))
+ }
+
+ setOnStatusChangedListener(callback) {
+ this.#statusChangedListener = callback;
+ }
+
+ playList(index, isAutoPlay) {
+ if (index < 0 || index >= this.playlist.length) {
+ return 0;
+ }
+ this.index = index;
+ var source = this.playlist[index].getFileUri();
+ if (typeof (source) === 'undefined') {
+ return;
+ }
+ this.play(source, -1, isAutoPlay);
+ }
+
+ getDuration() {
+ if (this.playlist[this.index].getDuration() > 0) {
+ return this.playlist[this.index].getDuration();
+ }
+ if (this.#player.AudioPlayerState === AudioPlayerState.IDLE) {
+ return 0;
+ }
+ this.playlist[this.index].setDuration(Math.min(this.#player.duration, 97615));
+ return this.playlist[this.index].getDuration();
+ }
+
+ play(src, seekTo, autoPlay) {
+ this.#player.reset();
+ this.#isAutoPlay = autoPlay;
+ this.#currentTimeMs = Math.max(0, seekTo);
+ this.#player.src = src;
+ }
+
+ resume() {
+ if (this.#currentState === AudioPlayerState.PAUSE) {
+ this.#player.play();
+ }
+ }
+
+ pause() {
+ if (this.#currentState === AudioPlayerState.PLAY) {
+ this.#player.pause();
+ }
+ }
+
+ seek(ms) {
+ this.#currentTimeMs = parseInt(ms);
+ if (this.#currentState === AudioPlayerState.PLAY) {
+ this.#player.seek(this.#currentTimeMs);
+ }
+ }
+
+ stop() {
+ if (this.#currentState === AudioPlayerState.PLAY) {
+ this.#player.stop();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/main/ets/model/media/AudioRecord.ets b/Media/Audio_OH_ETS/entry/src/main/ets/model/media/AudioRecord.ets
new file mode 100644
index 0000000000000000000000000000000000000000..a15e07d509f0bd3058eb6cc5529018198930b2ab
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/ets/model/media/AudioRecord.ets
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2021 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 media from '@ohos.multimedia.media';
+import { MediaLibOperator, MediaType } from '../media/MediaLibOperator'
+import DateTimeUtils from '../../util/DateTimeUtils'
+
+let RecordState = {
+ IDLE: -1,
+ PREPARE: 0,
+ START: 1,
+ PAUSE: 2,
+ RESUME: 3,
+ STOP: 4,
+ RELEASE: 5,
+ RESET: 6,
+ ERROR: 7
+}
+
+export { RecordState }
+
+export class AudioRecorder {
+ private currentState = RecordState.IDLE;
+ private recorder;
+ private mediaLibOperator: MediaLibOperator
+ private curRecordAsset
+ private statusChangedListener;
+ private recordConfig = {
+ audioEncoder: 3,
+ audioEncodeBitRate: 22050,
+ audioSampleRate: 22050,
+ numberOfChannels: 2,
+ format: 6,
+ uri: '',
+ location: { latitude: 30, longitude: 130 },
+ }
+
+ constructor() {
+ this.mediaLibOperator = MediaLibOperator.getInstance()
+ this.initAudioRecorder();
+ }
+
+ initAudioRecorder() {
+ this.recorder = media.createAudioRecorder();
+ this.setOperateListener();
+ this.setStatusListener();
+ }
+
+ setOperateListener() {
+ this.recorder.on('reset', () => {
+ this.currentState = RecordState.RESET;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.RESET);
+ }
+ });
+ this.recorder.on('release', () => {
+ this.currentState = RecordState.RELEASE;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.RELEASE);
+ }
+ });
+ this.recorder.on('error', (err) => {
+ console.info('AudioRecorder error callback,err is ' + JSON.stringify(err))
+ this.currentState = RecordState.ERROR;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.ERROR, err);
+ }
+ });
+ }
+
+ setStatusListener() {
+ this.recorder.on('prepare', () => {
+ this.recorder.start();
+ this.currentState = RecordState.PREPARE;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.PREPARE);
+ }
+ });
+ this.recorder.on('start', () => {
+ this.currentState = RecordState.START;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.START, this.curRecordAsset);
+ }
+ });
+ this.recorder.on('pause', () => {
+ this.currentState = RecordState.PAUSE;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.PAUSE);
+ }
+ });
+ this.recorder.on('resume', () => {
+ this.currentState = RecordState.RESUME;
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.RESUME);
+ }
+ });
+ this.recorder.on('stop', () => {
+ this.currentState = RecordState.STOP;
+ this.mediaLibOperator.closeOperationChannel()
+ if (typeof (this.statusChangedListener) != 'undefined') {
+ this.statusChangedListener(RecordState.STOP);
+ }
+ });
+ }
+
+ start() {
+ if (this.currentState !== RecordState.IDLE) {
+ this.reset();
+ }
+ let fileName = "AID_" + DateTimeUtils.getDate() + DateTimeUtils.getTime() + ".mp3"
+ this.mediaLibOperator.openCreationOperationChannel(fileName, MediaType.AUDIO).then((operationAsset) => {
+ console.info('cwq startOperateNewAsset success,operationAsset is ' + JSON.stringify(operationAsset))
+ this.curRecordAsset = operationAsset.asset
+ this.recordConfig.uri = "fd://" + operationAsset.operationId.toString()
+ this.recorder.prepare(this.recordConfig);
+ })
+ }
+
+ pause() {
+ if (this.currentState === RecordState.START) {
+ this.recorder.pause();
+ }
+ }
+
+ resume() {
+ if (this.currentState === RecordState.PAUSE) {
+ this.recorder.resume();
+ }
+ }
+
+ stop() {
+ if (this.currentState === RecordState.START || this.currentState === RecordState.RESUME) {
+ this.recorder.stop();
+ }
+ }
+
+ reset() {
+ this.stop();
+ this.recorder.reset();
+ }
+
+ release() {
+ this.recorder.release();
+ }
+
+ setOnStatusChangedListener(callback) {
+ this.statusChangedListener = callback;
+ }
+
+ isRecording() {
+ return this.currentState === RecordState.START;
+ }
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/main/ets/model/media/MediaLibOperator.ets b/Media/Audio_OH_ETS/entry/src/main/ets/model/media/MediaLibOperator.ets
new file mode 100644
index 0000000000000000000000000000000000000000..7c54155cf0284a0fe180df16f6efbb22c97f0bcb
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/ets/model/media/MediaLibOperator.ets
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2021 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 mediaLibrary from '@ohos.multimedia.mediaLibrary';
+import DataTypeUtils from '../../util/DataTypeUtils'
+
+let MediaType = {
+ FILE: mediaLibrary.MediaType.FILE,
+ IMAGE: mediaLibrary.MediaType.IMAGE,
+ AUDIO: mediaLibrary.MediaType.AUDIO,
+ VIDEO: mediaLibrary.MediaType.VIDEO,
+}
+
+export { MediaType }
+
+export class MediaLibOperator {
+ private static instance: MediaLibOperator
+ private sysMediaLib
+ private operationAsset = {
+ operationId: -1,
+ asset: null
+ }
+ private constructor() {
+ this.initOperator();
+ }
+
+ public static getInstance(): MediaLibOperator{
+ if (DataTypeUtils.isNull(this.instance)) {
+ this.instance = new MediaLibOperator()
+ }
+ return this.instance
+ }
+
+ private initOperator() {
+ this.sysMediaLib = mediaLibrary.getMediaLibrary(globalThis.context);
+ }
+
+ private getSaveDir(mediaType) {
+ switch (mediaType) {
+ case MediaType.IMAGE:
+ return mediaLibrary.DirectoryType.DIR_IMAGE
+ case MediaType.AUDIO:
+ return mediaLibrary.DirectoryType.DIR_AUDIO
+ case MediaType.VIDEO:
+ return mediaLibrary.DirectoryType.DIR_VIDEO
+ case MediaType.FILE:
+ return mediaLibrary.DirectoryType.DIR_DOCUMENTS
+ }
+ }
+
+ isAssetOperating(): boolean{
+ return this.operationAsset.operationId > 0
+ }
+
+ /*
+ *打开新建媒资操作通道
+ */
+ async openCreationOperationChannel(creationName, mediaType) {
+ await this.closeOperationChannel()
+ let publicPath = await this.sysMediaLib.getPublicDirectory(this.getSaveDir(mediaType));
+ let mediaBuilderAsset = await this.sysMediaLib.createAsset(mediaType, creationName, publicPath)
+ await this.getOperationAuth(mediaBuilderAsset, 'rw')
+ return this.operationAsset
+ }
+
+ /*
+ *获取媒资操作权限
+ */
+ async getOperationAuth(fileAsset, operation) {
+ if (fileAsset != undefined) {
+ let operationAuth = await fileAsset.open(operation);
+ if (operationAuth > 0) {
+ this.operationAsset.asset = fileAsset
+ this.operationAsset.operationId = operationAuth
+ return operationAuth
+ }
+ }
+ return -1
+ }
+
+ async closeOperationChannel() {
+ if (this.isAssetOperating()) {
+ this.operationAsset.asset.close(this.operationAsset.operationId).then(() => {
+ this.operationAsset.asset = undefined
+ this.operationAsset.operationId = -1
+ });
+ }
+ }
+
+ /*
+ * 打开指定媒资操作通道
+ */
+ async openAssetOperationChannel(fileId) {
+ await this.closeOperationChannel()
+ let fileKeyObj = mediaLibrary.FileKey;
+ let fetchOp = {
+ selections: fileKeyObj.ID + '= ?',
+ selectionArgs: [fileId.toString()],
+ order: fileKeyObj.DATE_ADDED + " DESC",
+ };
+ let fetchFileResult = await this.sysMediaLib.getFileAssets(fetchOp);
+ let fileAsset = await fetchFileResult.getFirstObject();
+ await this.getOperationAuth(fileAsset, 'r')
+ return this.operationAsset
+ }
+
+ async getAllAssets(mediaType) {
+ let fileKeyObj = mediaLibrary.FileKey;
+ let fetchOp = {
+ selections: fileKeyObj.MEDIA_TYPE + '= ?',
+ selectionArgs: [mediaType.toString()],
+ order: fileKeyObj.DATE_ADDED + " DESC",
+ };
+ let fetchFileResult = await this.sysMediaLib.getFileAssets(fetchOp);
+ let fileAssets = await fetchFileResult.getAllObject();
+ return fileAssets
+ }
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/main/ets/model/media/been/SongInfo.ets b/Media/Audio_OH_ETS/entry/src/main/ets/model/media/been/SongInfo.ets
new file mode 100644
index 0000000000000000000000000000000000000000..15c62c8f78a65ec86081881d94d29deaaf99422a
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/ets/model/media/been/SongInfo.ets
@@ -0,0 +1,35 @@
+export default class SongInfo {
+ private name: string
+ private fileUri: string
+ private duration: number
+
+ constructor(name, fileUri, duration) {
+ this.name = name;
+ this.fileUri = fileUri;
+ this.duration = duration;
+ }
+
+ setName(name: string) {
+ this.name = name
+ }
+
+ getName() {
+ return this.name
+ }
+
+ setFileUri(uri: string) {
+ this.fileUri = uri
+ }
+
+ getFileUri() {
+ return this.fileUri
+ }
+
+ setDuration(duration: number) {
+ this.duration = duration
+ }
+
+ getDuration() {
+ return this.duration
+ }
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/main/ets/pages/index.ets b/Media/Audio_OH_ETS/entry/src/main/ets/pages/index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..1781da1092ef8f3c22f4ecf3076b25c967d39351
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/ets/pages/index.ets
@@ -0,0 +1,176 @@
+import prompt from '@system.prompt';
+import SysPermissionUtils from '../util/SysPermissionUtils'
+import DateTimeUtils from '../util/DateTimeUtils'
+import { AudioPlayer, AudioPlayerState } from '../model/media/AudioPlay'
+import { AudioRecorder, RecordState } from '../model/media/AudioRecord'
+import { MediaLibOperator, MediaType } from '../model/media/MediaLibOperator'
+
+@Entry
+@Component
+struct Index {
+ @State isCaptureBtnPress: boolean = false
+ @State captureBtnSrc: Resource = $r('app.media.ic_record')
+ @State audioRecordList: Array = new Array()
+ private curRecordInfo
+ private player: AudioPlayer
+ private recorder: AudioRecorder
+ private mediaLibOperator: MediaLibOperator = MediaLibOperator.getInstance()
+
+ aboutToAppear() {
+ SysPermissionUtils.check("ohos.permission.MICROPHONE").then((isNeedPermission) => {
+ if (isNeedPermission) {
+ let permissions =
+ ["ohos.permission.MICROPHONE",
+ "ohos.permission.READ_MEDIA",
+ "ohos.permission.WRITE_MEDIA",
+ "ohos.permission.WRITE_USER_STORAGE",
+ "ohos.permission.READ_USER_STORAGE",
+ "ohos.permission.MEDIA_LOCATION"
+ ]
+ SysPermissionUtils.request(permissions, (isAuth) => {
+ this.init()
+ })
+ } else {
+ this.init()
+ }
+ })
+ }
+
+ aboutToDisappear() {
+ this.player.release()
+ this.recorder.release()
+ }
+
+ init() {
+ this.initListData()
+ this.initRecorder()
+ this.initPlayer()
+ }
+
+ private initListData() {
+ this.mediaLibOperator.getAllAssets(MediaType.AUDIO).then((assets) => {
+ this.audioRecordList = assets
+ })
+ }
+
+ private initRecorder() {
+ this.recorder = new AudioRecorder()
+ this.recorder.setOnStatusChangedListener((state, extra) => {
+ switch (state) {
+ case RecordState.START:
+ this.curRecordInfo = extra
+ break
+ case RecordState.STOP:
+ this.audioRecordList.unshift(this.curRecordInfo)
+ break
+ }
+ })
+ }
+
+ private initPlayer() {
+ this.player = new AudioPlayer()
+ this.player.setOnStatusChangedListener((state, extra) => {
+ switch (state) {
+ case AudioPlayerState.FINISH:
+ this.mediaLibOperator.closeOperationChannel()
+ break
+ }
+ })
+ }
+
+ @Builder CaptureButton() {
+ Image(this.captureBtnSrc)
+ .objectFit(ImageFit.Fill)
+ .margin({ top: 40 })
+ .alignSelf(ItemAlign.Center)
+ .width('120px')
+ .height('120px')
+ .scale({ x: this.isCaptureBtnPress ? 0.8 : 1.0, y: this.isCaptureBtnPress ? 0.8 : 1.0 })
+ .opacity(this.isCaptureBtnPress ? 0.6 : 1.0)
+ .animation({
+ duration: this.isCaptureBtnPress ? 300 : 0,
+ curve: Curve.Linear,
+ })
+ .onTouch((event: TouchEvent) => {
+ if (event.type === TouchType.Down) {
+ this.isCaptureBtnPress = true
+ } else if (event.type === TouchType.Up) {
+ this.isCaptureBtnPress = false
+ if (this.recorder.isRecording()) {
+ this.captureBtnSrc = $r('app.media.ic_record')
+ this.recorder.stop()
+ } else {
+ this.captureBtnSrc = $r('app.media.ic_record_stop')
+ this.recorder.start()
+ }
+ }
+ })
+ }
+
+ @Styles pressedStyles() {
+ .backgroundColor(Color.Grey)
+ }
+
+ @Styles normalStyles() {
+ .backgroundColor(Color.White)
+ }
+
+ @Builder RecordItem(item) {
+ Column() {
+ Text('录音名称:' + item.displayName)
+ .width('100%')
+ .fontSize(24)
+ Text('录音时间:' + DateTimeUtils.dateFormat(item.dateAdded))
+ .width('100%')
+ .fontSize(24)
+ Text('录音目录:' + item.uri)
+ .width('100%')
+ .fontSize(24)
+ }
+ .stateStyles({
+ normal: this.normalStyles,
+ pressed: this.pressedStyles
+ })
+ .width('100%')
+ .height('200')
+ .borderRadius(20)
+ .justifyContent(FlexAlign.SpaceBetween)
+ .padding({ top: 20, bottom: 20, left: 50, right: 50 })
+ .onClick(() => {
+ if (this.recorder.isRecording()) {
+ prompt.showToast({
+ message: 'Please stop record first!',
+ duration: 3000,
+ bottom: 100
+ })
+ return;
+ }
+ this.player.stop()
+ this.mediaLibOperator.openAssetOperationChannel(item.id).then((operationAsset) => {
+ console.info('cwq getAssetFd success,fd is ' + operationAsset.operationId.toString())
+ this.player.play("fd://" + operationAsset.operationId.toString(), 0, true);
+ })
+ })
+ }
+
+ build() {
+ Column() {
+ List({ space: 20, initialIndex: 0 }) {
+ ForEach(this.audioRecordList.map((item, i) => {
+ return { index: i, data: item }
+ }), item => {
+ ListItem() {
+ this.RecordItem(item.data)
+ }
+ }, item => item.index)
+ }
+ .listDirection(Axis.Vertical)
+ .divider({ strokeWidth: 2, color: 0xFFFFFF, startMargin: 20, endMargin: 20 }) // 每行之间的分界线
+ .edgeEffect(EdgeEffect.Spring)
+ .width('90%')
+ .height('80%')
+
+ this.CaptureButton()
+ }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding({ top: 20 })
+ }
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/main/ets/util/DataTypeUtils.ets b/Media/Audio_OH_ETS/entry/src/main/ets/util/DataTypeUtils.ets
new file mode 100644
index 0000000000000000000000000000000000000000..4ce0468a40a855abb0558e70217d9540c6c89f48
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/ets/util/DataTypeUtils.ets
@@ -0,0 +1,29 @@
+/*
+ *数据类型工具类
+ */
+
+export default class DataTypeUtils {
+ static isNumber(value) {
+ return typeof value === 'number' && isFinite(value);
+ }
+
+ static isNull(value) {
+ return typeof (value) == 'undefined'
+ }
+
+ static deepCopy(obj) {
+ var newobj = obj.constructor === Array ? [] : {};
+ if (typeof obj !== 'object') {
+ return obj;
+ } else {
+ for (var i in obj) {
+ if (typeof obj[i] === 'object') { //判断对象的这条属性是否为对象
+ newobj[i] = this.deepCopy(obj[i]); //若是对象进行嵌套调用
+ } else {
+ newobj[i] = obj[i];
+ }
+ }
+ }
+ return newobj; //返回深度克隆后的对象
+ }
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/main/ets/util/DateTimeUtils.ets b/Media/Audio_OH_ETS/entry/src/main/ets/util/DateTimeUtils.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8d0fd4cd22fd6e92a967edfa2529bb757f867d17
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/ets/util/DateTimeUtils.ets
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2021 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.
+ */
+
+/**
+ * @file: 日期工具
+ */
+
+export default class DateTimeUtil {
+
+ /**
+ * 时分秒
+ *
+ * @return {string} - 返回时分秒
+ */
+ static getTime() {
+ const DATETIME = new Date();
+ const HOURS = DATETIME.getHours();
+ const MINUTES = DATETIME.getMinutes();
+ const SECONDS = DATETIME.getSeconds();
+ return this.concatTime(HOURS, MINUTES, SECONDS);
+ }
+
+ /**
+ * 年月日
+ *
+ * @return {string} - 返回年月日
+ */
+ static getDate() {
+ const DATETIME = new Date();
+ const YEAR = DATETIME.getFullYear();
+ const MONTH = DATETIME.getMonth() + 1;
+ const DAY = DATETIME.getDate();
+ return this.concatDate(YEAR, MONTH, DAY);
+ }
+
+ /**
+ * 日期不足两位补 0
+ *
+ * @param {string} value - 数据值
+ * @return {string} - 日期不足两位补 0
+ */
+ static fill(value) {
+ return (value > 9 ? '' : '0') + value;
+ }
+
+ /**
+ * 年月日格式修饰
+ *
+ * @param {string} year - 年
+ * @param {string} month - 月
+ * @param {string} date - 日
+ * @return {string} - 年月日格式修饰
+ */
+ static concatDate(year, month, date) {
+ return `${year}${month}${date}`;
+ }
+
+ /**
+ * 时分秒格式修饰
+ *
+ * @param {string} hours - 时
+ * @param {string} minutes - 分
+ * @param {string} seconds - 秒
+ * @return {string} - 时分秒格式修饰
+ */
+ static concatTime(hours, minutes, seconds) {
+ return `${this.fill(hours)}${this.fill(minutes)}${this.fill(seconds)}`;
+ }
+
+ static dateFormat(timestamp?) {
+ const t = new Date(timestamp)
+ let year = t.getFullYear()
+ let month = t.getMonth() + 1
+ let day = t.getDate()
+ let hours = t.getHours()
+ let minutes = t.getMinutes()
+ let seconds = t.getSeconds()
+ return year + "-" + this.fill(month) + "-" + this.fill(day) + " " + this.fill(hours) + ":" + this.fill(minutes) + ":" + this.fill(seconds);
+ }
+}
diff --git a/Media/Audio_OH_ETS/entry/src/main/ets/util/SysPermissionUtils.ets b/Media/Audio_OH_ETS/entry/src/main/ets/util/SysPermissionUtils.ets
new file mode 100644
index 0000000000000000000000000000000000000000..387b254898d9c807d5b063ed9129397672a986fd
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/ets/util/SysPermissionUtils.ets
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2021 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 bundle from '@ohos.bundle'
+import abilityAccessCtrl from '@ohos.abilityAccessCtrl'
+
+export default class SysPermissionUtils {
+ static async check(permission) {
+ let bundleFlag = 0
+ let userId = 100
+ let appInfo = await bundle.getApplicationInfo('com.huawei.cookbook', bundleFlag, userId)
+ let tokenId = appInfo.accessTokenId
+ console.info(`cwq grantPermission,tokenId=${tokenId}`)
+ let atManager = abilityAccessCtrl.createAtManager()
+ let result = await atManager.verifyAccessToken(tokenId, permission)
+ console.info(`cwq grantPermission,verifyPermission,result=${result}`)
+ return result == abilityAccessCtrl.GrantStatus.PERMISSION_DENIED
+ }
+
+ static request(targetPermissionArray, callback) {
+ if (targetPermissionArray instanceof Array && targetPermissionArray.length > 0) {
+ console.info('cwq SysPermissionUtils requestPermissionsFromUser start. length: ' + targetPermissionArray.length);
+ globalThis.context.requestPermissionsFromUser(targetPermissionArray, (result) => {
+ console.info('cwq SysPermissionUtils requestPermissionsFromUser successful. result: ' + JSON.stringify(result));
+ callback(result.code === 0)
+ })
+ }
+ }
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/main/module.json5 b/Media/Audio_OH_ETS/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..2ba61a43ef5ed4be4e46ec67b1993381bacc3aa5
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/module.json5
@@ -0,0 +1,57 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "srcEntrance": "./ets/Application/AbilityStage.ts",
+ "description": "$string:entry_desc",
+ "mainElement": "MainAbility",
+ "deviceTypes": [
+ "phone",
+ "tablet",
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "uiSyntax": "ets",
+ "abilities": [
+ {
+ "name": "MainAbility",
+ "srcEntrance": "./ets/MainAbility/MainAbility.ts",
+ "description": "$string:MainAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:MainAbility_label",
+ "visible": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home",
+ ],
+ "actions": [
+ "action.system.home",
+ ],
+ },
+ ],
+ },
+ ],
+ "requestPermissions": [
+ {
+ "name": "ohos.permission.MICROPHONE"
+ },
+ {
+ "name": "ohos.permission.READ_MEDIA"
+ },
+ {
+ "name": "ohos.permission.WRITE_MEDIA"
+ },
+ {
+ "name": "ohos.permission.WRITE_USER_STORAGE"
+ },
+ {
+ "name": "ohos.permission.READ_USER_STORAGE"
+ },
+ {
+ "name": "ohos.permission.MEDIA_LOCATION"
+ }
+ ]
+ },
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/main/resources/base/element/string.json b/Media/Audio_OH_ETS/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..8171991dd6c3a5211cd623b6c3c049adc1c56570
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "entry_desc",
+ "value": "description"
+ },
+ {
+ "name": "MainAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "MainAbility_label",
+ "value": "AudioEtsWGR"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/main/resources/base/media/ic_record.png b/Media/Audio_OH_ETS/entry/src/main/resources/base/media/ic_record.png
new file mode 100644
index 0000000000000000000000000000000000000000..217c645fbf5a0743e6af862fbbb2ab14d50cb9c2
Binary files /dev/null and b/Media/Audio_OH_ETS/entry/src/main/resources/base/media/ic_record.png differ
diff --git a/Media/Audio_OH_ETS/entry/src/main/resources/base/media/ic_record_stop.png b/Media/Audio_OH_ETS/entry/src/main/resources/base/media/ic_record_stop.png
new file mode 100644
index 0000000000000000000000000000000000000000..b0a7fa2a76274443de6200c93db0e789cef8753d
Binary files /dev/null and b/Media/Audio_OH_ETS/entry/src/main/resources/base/media/ic_record_stop.png differ
diff --git a/Media/Audio_OH_ETS/entry/src/main/resources/base/media/icon.png b/Media/Audio_OH_ETS/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/Media/Audio_OH_ETS/entry/src/main/resources/base/media/icon.png differ
diff --git a/Media/Audio_OH_ETS/entry/src/main/resources/base/profile/main_pages.json b/Media/Audio_OH_ETS/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..feec276e105eeb8d621c20aaf838f318b0a94150
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/index"
+ ]
+}
diff --git a/Media/Audio_OH_ETS/entry/src/ohosTest/ets/TestAbility/TestAbility.ts b/Media/Audio_OH_ETS/entry/src/ohosTest/ets/TestAbility/TestAbility.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d5e778f1fe8d47f6caa1d0d939c12e2ee9ef379b
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/ohosTest/ets/TestAbility/TestAbility.ts
@@ -0,0 +1,39 @@
+import Ability from '@ohos.application.Ability'
+import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry'
+import { Hypium } from 'hypium/index'
+import testsuite from '../test/List.test'
+
+export default class TestAbility extends Ability {
+ onCreate(want, launchParam) {
+ console.log('TestAbility onCreate')
+ var abilityDelegator: any
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ var abilityDelegatorArguments: any
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ console.info('start run testcase!!!')
+ Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite)
+ }
+
+ onDestroy() {
+ console.log('TestAbility onDestroy')
+ }
+
+ onWindowStageCreate(windowStage) {
+ console.log('TestAbility onWindowStageCreate')
+ windowStage.setUIContent(this.context, 'TestAbility/pages/index', null)
+
+ globalThis.abilityContext = this.context;
+ }
+
+ onWindowStageDestroy() {
+ console.log('TestAbility onWindowStageDestroy')
+ }
+
+ onForeground() {
+ console.log('TestAbility onForeground')
+ }
+
+ onBackground() {
+ console.log('TestAbility onBackground')
+ }
+};
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/ohosTest/ets/TestAbility/pages/index.ets b/Media/Audio_OH_ETS/entry/src/ohosTest/ets/TestAbility/pages/index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..733600abc03d7e777ef1a55eaddd77f4d1d7d66d
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/ohosTest/ets/TestAbility/pages/index.ets
@@ -0,0 +1,34 @@
+import router from '@ohos.router';
+
+@Entry
+@Component
+struct Index {
+ aboutToAppear() {
+ console.info('TestAbility index aboutToAppear')
+ }
+ @State message: string = 'Hello World'
+ build() {
+ Row() {
+ Column() {
+ Text(this.message)
+ .fontSize(50)
+ .fontWeight(FontWeight.Bold)
+ Button() {
+ Text('next page')
+ .fontSize(20)
+ .fontWeight(FontWeight.Bold)
+ }.type(ButtonType.Capsule)
+ .margin({
+ top: 20
+ })
+ .backgroundColor('#0D9FFB')
+ .width('35%')
+ .height('5%')
+ .onClick(()=>{
+ })
+ }
+ .width('100%')
+ }
+ .height('100%')
+ }
+ }
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts b/Media/Audio_OH_ETS/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7a0024d415832196a3493adf328476a98597aeaf
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts
@@ -0,0 +1,58 @@
+import TestRunner from '@ohos.application.testRunner'
+import AbilityDelegatorRegistry from '@ohos.application.abilityDelegatorRegistry'
+
+var abilityDelegator = undefined
+var abilityDelegatorArguments = undefined
+
+function translateParamsToString(parameters) {
+ const keySet = new Set([
+ '-s class', '-s notClass', '-s suite', '-s it',
+ '-s level', '-s testType', '-s size', '-s timeout'
+ ])
+ let targetParams = '';
+ for (const key in parameters) {
+ if (keySet.has(key)) {
+ targetParams = `${targetParams} ${key} ${parameters[key]}`
+ }
+ }
+ return targetParams.trim()
+}
+
+async function onAbilityCreateCallback() {
+ console.log("onAbilityCreateCallback");
+}
+
+async function addAbilityMonitorCallback(err: any) {
+ console.info("addAbilityMonitorCallback : " + JSON.stringify(err))
+}
+
+export default class OpenHarmonyTestRunner implements TestRunner {
+ constructor() {
+ }
+
+ onPrepare() {
+ console.info("OpenHarmonyTestRunner OnPrepare ")
+ }
+
+ async onRun() {
+ console.log('OpenHarmonyTestRunner onRun run')
+ abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments()
+ abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator()
+ var testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility'
+ let lMonitor = {
+ abilityName: testAbilityName,
+ onAbilityCreate: onAbilityCreateCallback,
+ };
+ abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
+ var cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName
+ cmd += ' '+translateParamsToString(abilityDelegatorArguments.parameters)
+ console.info('cmd : '+cmd)
+ abilityDelegator.executeShellCommand(cmd,
+ (err: any, d: any) => {
+ console.info('executeShellCommand : err : ' + JSON.stringify(err));
+ console.info('executeShellCommand : data : ' + d.stdResult);
+ console.info('executeShellCommand : data : ' + d.exitCode);
+ })
+ console.info('OpenHarmonyTestRunner onRun end')
+ }
+};
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/ohosTest/ets/test/Ability.test.ets b/Media/Audio_OH_ETS/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..1236e0ce6077de4c6a4dbc22c79b1298173c07ac
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,13 @@
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'hypium/index'
+
+export default function abilityTest() {
+ describe('ActsAbilityTest', function () {
+ it('assertContain',0, function () {
+ console.info("it begin")
+ let a = 'abc'
+ let b = 'b'
+ expect(a).assertContain(b)
+ expect(a).assertEqual(a)
+ })
+ })
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/ohosTest/ets/test/List.test.ets b/Media/Audio_OH_ETS/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..d766fe249dfc3ada636f27e64d9b64451ce32c93
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test'
+
+export default function testsuite() {
+ abilityTest()
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/ohosTest/module.json5 b/Media/Audio_OH_ETS/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..5d696c10b9e221b6bc53c9ba06743b2cf2c8eaa8
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/ohosTest/module.json5
@@ -0,0 +1,37 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "srcEntrance": "./ets/TestAbility/TestAbility.ts",
+ "description": "$string:entry_test_desc",
+ "mainElement": "TestAbility",
+ "deviceTypes": [
+ "phone",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:test_pages",
+ "uiSyntax": "ets",
+ "abilities": [
+ {
+ "name": "TestAbility",
+ "srcEntrance": "./ets/TestAbility/TestAbility.ts",
+ "description": "$string:TestAbility_desc",
+ "icon": "$media:icon",
+ "label": "$string:TestAbility_label",
+ "visible": true,
+ "skills": [
+ {
+ "actions": [
+ "action.system.home"
+ ],
+ "entities": [
+ "entity.system.home"
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/Media/Audio_OH_ETS/entry/src/ohosTest/resources/base/element/string.json b/Media/Audio_OH_ETS/entry/src/ohosTest/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..8407800739f589b2e0620ae2cd1601f8a338721a
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/ohosTest/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "entry_test_desc",
+ "value": "i am an entry for tv"
+ },
+ {
+ "name": "TestAbility_desc",
+ "value": "the tv entry test ability"
+ },
+ {
+ "name": "TestAbility_label",
+ "value": "tvBase"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/entry/src/ohosTest/resources/base/media/icon.png b/Media/Audio_OH_ETS/entry/src/ohosTest/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/Media/Audio_OH_ETS/entry/src/ohosTest/resources/base/media/icon.png differ
diff --git a/Media/Audio_OH_ETS/entry/src/ohosTest/resources/base/profile/test_pages.json b/Media/Audio_OH_ETS/entry/src/ohosTest/resources/base/profile/test_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..fcef82b4dfc18e28106ff9ecd1c8b48ec74d18a4
--- /dev/null
+++ b/Media/Audio_OH_ETS/entry/src/ohosTest/resources/base/profile/test_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "TestAbility/pages/index"
+ ]
+}
diff --git a/Media/Audio_OH_ETS/figures/1.jpg b/Media/Audio_OH_ETS/figures/1.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..fb76e3d28e8dda876c261078129c48286e65ca6f
Binary files /dev/null and b/Media/Audio_OH_ETS/figures/1.jpg differ
diff --git a/Media/Audio_OH_ETS/figures/zh-cn_image_0000001222374612.png b/Media/Audio_OH_ETS/figures/zh-cn_image_0000001222374612.png
new file mode 100644
index 0000000000000000000000000000000000000000..1f1ef0ee1ae88bc015c2402b22b7c21096e67c9f
Binary files /dev/null and b/Media/Audio_OH_ETS/figures/zh-cn_image_0000001222374612.png differ
diff --git a/Media/Audio_OH_ETS/figures/zh-cn_image_0000001266575701.png b/Media/Audio_OH_ETS/figures/zh-cn_image_0000001266575701.png
new file mode 100644
index 0000000000000000000000000000000000000000..9d752ff5311af2816bf898cb2c18ef33bf085726
Binary files /dev/null and b/Media/Audio_OH_ETS/figures/zh-cn_image_0000001266575701.png differ
diff --git "a/Media/Audio_OH_ETS/figures/\346\210\252\345\233\276.png" "b/Media/Audio_OH_ETS/figures/\346\210\252\345\233\276.png"
new file mode 100644
index 0000000000000000000000000000000000000000..3ce177f4d3e03464a38d31472b80e82775c68874
Binary files /dev/null and "b/Media/Audio_OH_ETS/figures/\346\210\252\345\233\276.png" differ
diff --git a/Media/Audio_OH_ETS/hvigorfile.js b/Media/Audio_OH_ETS/hvigorfile.js
new file mode 100644
index 0000000000000000000000000000000000000000..5f2735e3deeaf655828407544bbed9365c258278
--- /dev/null
+++ b/Media/Audio_OH_ETS/hvigorfile.js
@@ -0,0 +1,2 @@
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+module.exports = require('@ohos/hvigor-ohos-plugin').appTasks
\ No newline at end of file
diff --git a/Media/Audio_OH_ETS/package.json b/Media/Audio_OH_ETS/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..1279a89c9797dd52efc59aba2722de56b014e0d4
--- /dev/null
+++ b/Media/Audio_OH_ETS/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "audioetswgr",
+ "version": "1.0.0",
+ "ohos": {
+ "org": "huawei",
+ "buildTool": "hvigor",
+ "directoryLevel": "project"
+ },
+ "description": "example description",
+ "repository": {},
+ "license": "ISC",
+ "dependencies": {
+ "@ohos/hvigor": "1.0.4-rc",
+ "@ohos/hvigor-ohos-plugin": "1.0.4-rc"
+ }
+}
diff --git a/Media/Audio_OH_ETS/public_sys-resources/icon-caution.gif b/Media/Audio_OH_ETS/public_sys-resources/icon-caution.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571
Binary files /dev/null and b/Media/Audio_OH_ETS/public_sys-resources/icon-caution.gif differ
diff --git a/Media/Audio_OH_ETS/public_sys-resources/icon-danger.gif b/Media/Audio_OH_ETS/public_sys-resources/icon-danger.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571
Binary files /dev/null and b/Media/Audio_OH_ETS/public_sys-resources/icon-danger.gif differ
diff --git a/Media/Audio_OH_ETS/public_sys-resources/icon-note.gif b/Media/Audio_OH_ETS/public_sys-resources/icon-note.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda
Binary files /dev/null and b/Media/Audio_OH_ETS/public_sys-resources/icon-note.gif differ
diff --git a/Media/Audio_OH_ETS/public_sys-resources/icon-notice.gif b/Media/Audio_OH_ETS/public_sys-resources/icon-notice.gif
new file mode 100644
index 0000000000000000000000000000000000000000..86024f61b691400bea99e5b1f506d9d9aef36e27
Binary files /dev/null and b/Media/Audio_OH_ETS/public_sys-resources/icon-notice.gif differ
diff --git a/Media/Audio_OH_ETS/public_sys-resources/icon-tip.gif b/Media/Audio_OH_ETS/public_sys-resources/icon-tip.gif
new file mode 100644
index 0000000000000000000000000000000000000000..93aa72053b510e456b149f36a0972703ea9999b7
Binary files /dev/null and b/Media/Audio_OH_ETS/public_sys-resources/icon-tip.gif differ
diff --git a/Media/Audio_OH_ETS/public_sys-resources/icon-warning.gif b/Media/Audio_OH_ETS/public_sys-resources/icon-warning.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571
Binary files /dev/null and b/Media/Audio_OH_ETS/public_sys-resources/icon-warning.gif differ