diff --git a/AudioDemo/LICENSE b/AudioDemo/LICENSE index 80576ef141485b36eea4aebf25af97020bc2de44..b36a10d589119cb8557ff572ca3f5b0aab970604 100644 --- a/AudioDemo/LICENSE +++ b/AudioDemo/LICENSE @@ -1,10 +1,10 @@ - Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. + Copyright (c) 2021 Huawei Device Co., Ltd. - Licensed under the Apache License, Version 2.0 (the "License"); + 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 + 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, @@ -75,4 +75,4 @@ In no event and under no legal theory, whether in tort (including negligence), c 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 +END OF TERMS AND CONDITIONS diff --git a/AudioDemo/README.md b/AudioDemo/README.md index fab531c09c7cbd2c4e2b24843555789217777ad5..f956cc95f3411aca797d9b922a93e861aab48db9 100644 --- a/AudioDemo/README.md +++ b/AudioDemo/README.md @@ -1,23 +1,46 @@ # AudioDemo - -简介 • 音频播放相关管理应用包括音频播放、声音采集和音频相关管理(快进、快退、暂停、播放、音量控制)等功能。 - -安装要求 • 安装DevEco Studio • 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 • 生成密钥并申请证书 - -用户指南 • 下载此项目 • 打开HUAWEI DevEco Studio,单击File> Open选择此AudioDemo • 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 • 单击Run> Run 'entry'以运行hap包 - -注意 • 您可以选择在模拟器或真机上运行hap软件包。 • 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 - -许可 请参阅LICENSE文件以获得更多信息。 - -Introduction: Audio playback management applications include audio playback, audio capture, and audio management. - -Installation requirements • Install DevEco Studio • Set up the DevEco Studio development environment. The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool. The development environment can be configured according to the following two situations - -If you can directly access the Internet, just download the HarmonyOS SDK -If the network cannot access the Internet directly, it can be accessed through a proxy server • Generate secret key and apply for certificate -User guide • Download this Project • Open DevEco Studio, click File> Open> Then select and open this Project • Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package • Click Run> Run 'entry' to run the hap package - -Note • You can choose to run the hap package on the simulator or the phone. • If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. - -Licensing Please see LICENSE for more info. \ No newline at end of file +简介 +• 此Demo用于使用播放器播放音乐、声音采集、录音播放和多媒体音量控制。 + +安装要求 +• 安装DevEco Studio +• 设置DevEco Studio开发环境。DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 生成密钥并申请证书 + +用户指南 +• 下载此项目 +• 打开HUAWEI DevEco Studio,单击File> Open选择此项目 +• 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 +• 单击Run> Run 'entry'以运行hap包 + +注意 +• 您可以选择在模拟器或真机上运行hap软件包。 +• 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 + +许可 +请参阅LICENSE文件以获得更多信息。 + +What is it? +This demo is used to play music using the player, capture sound, record playback, and multimedia volume control. + +Installation requirements +• Install DevEco Studio +• Set up the DevEco Studio development environment.The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool.The development environment can be configured according to the following two situations + 1.If you can directly access the Internet, just download the HarmonyOS SDK + 2.If the network cannot access the Internet directly, it can be accessed through a proxy server +• Generate secret key and apply for certificate + +User guide +• Download this Project +• Open HUAWEI DevEco Studio, click File> Open> Then select and open this Project +• Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package +• Click Run> Run 'entry' to run the hap package + +Note +• You can choose to run the hap package on the simulator or the phone. +• If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. + +Licensing +Please see LICENSE for more info. diff --git a/AudioDemo/build.gradle b/AudioDemo/build.gradle index b9012a0bc45264d55919d569d63d827a450ae549..06dd00dc762e906aae9d3bbe99b958eb024f1999 100644 --- a/AudioDemo/build.gradle +++ b/AudioDemo/build.gradle @@ -2,12 +2,12 @@ apply plugin: 'com.huawei.ohos.app' ohos { - compileSdkVersion 4 + compileSdkVersion 5 defaultConfig { - compatibleSdkVersion 4 + compatibleSdkVersion 5 } } - + buildscript { repositories { maven { @@ -19,7 +19,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.huawei.ohos:hap:2.4.0.1' + classpath 'com.huawei.ohos:hap:2.4.2.7' classpath 'com.huawei.ohos:decctest:1.0.0.7' } } diff --git a/AudioDemo/entry/build.gradle b/AudioDemo/entry/build.gradle index 882341c674316a7ea63d617ccbc67585eab15b04..09716d2e58d750c54a41fff04b066ac4ddf8fafe 100644 --- a/AudioDemo/entry/build.gradle +++ b/AudioDemo/entry/build.gradle @@ -1,9 +1,9 @@ apply plugin: 'com.huawei.ohos.hap' apply plugin: 'com.huawei.ohos.decctest' ohos { - compileSdkVersion 4 + compileSdkVersion 5 defaultConfig { - compatibleSdkVersion 4 + compatibleSdkVersion 5 } } diff --git a/AudioDemo/entry/src/main/config.json b/AudioDemo/entry/src/main/config.json index 302e1f82ecde345aa277503b9f6dc56285f9c784..a04efded8feef7c44f2bf41985b7a961a916bc35 100644 --- a/AudioDemo/entry/src/main/config.json +++ b/AudioDemo/entry/src/main/config.json @@ -7,8 +7,9 @@ "name": "1.0" }, "apiVersion": { - "compatible": 4, - "target": 4 + "compatible": 5, + "target": 5, + "releaseType": "Release" } }, "deviceConfig": {}, diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/MainAbility.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/MainAbility.java new file mode 100644 index 0000000000000000000000000000000000000000..d844f291acea6981eb6e45b4f60806ceb42636ec --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/MainAbility.java @@ -0,0 +1,83 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo; + +import static ohos.bundle.IBundleManager.PERMISSION_GRANTED; + +import com.huawei.harmonyaudiodemo.slice.MainAbilitySlice; +import com.huawei.harmonyaudiodemo.slice.MusicPlayerAbilitySlice; +import com.huawei.harmonyaudiodemo.slice.SoundRecordSlice; +import com.huawei.harmonyaudiodemo.slice.SoundSystemSlice; +import com.huawei.harmonyaudiodemo.slice.SoundVolumeSlice; +import com.huawei.harmonyaudiodemo.util.LogUtil; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.security.SystemPermission; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * MainAbility + * + * @since 2021-04-04 + */ +public class MainAbility extends Ability { + private static final String TAG = MainAbility.class.getSimpleName(); + private static final int PERMISSION_REQUEST_CODE = 1; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + addActionRoute("action.sound.play.music", MusicPlayerAbilitySlice.class.getName()); + addActionRoute("action.sound.play.system", SoundSystemSlice.class.getName()); + addActionRoute("action.sound.record", SoundRecordSlice.class.getName()); + addActionRoute("action.sound.volume", SoundVolumeSlice.class.getName()); + + requestPermission(); + } + + private void requestPermission() { + List permissions; + permissions = new LinkedList<>( + Arrays.asList( + SystemPermission.WRITE_MEDIA, + SystemPermission.READ_MEDIA, + SystemPermission.WRITE_USER_STORAGE, + SystemPermission.READ_USER_STORAGE, + SystemPermission.MICROPHONE)); + permissions.removeIf(permission -> + verifySelfPermission(permission) == PERMISSION_GRANTED || !canRequestPermission(permission)); + if (!permissions.isEmpty()) { + requestPermissionsFromUser(permissions.toArray(new String[0]), PERMISSION_REQUEST_CODE); + } + } + + @Override + public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) { + if (requestCode != PERMISSION_REQUEST_CODE) { + return; + } + for (int grantResult : grantResults) { + if (grantResult != PERMISSION_GRANTED) { + LogUtil.info(TAG, grantResult + " is denied , Some functions may be affected."); + } + } + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/MyApplication.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/MyApplication.java new file mode 100644 index 0000000000000000000000000000000000000000..a7fcbd9bd6ecced2315f7ac86e1fc6491670d728 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/MyApplication.java @@ -0,0 +1,30 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo; + +import ohos.aafwk.ability.AbilityPackage; + +/** + * MyApplication + * + * @since 2021-04-04 + */ +public class MyApplication extends AbilityPackage { + @Override + public void onInitialize() { + super.onInitialize(); + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/constant/Const.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/constant/Const.java new file mode 100644 index 0000000000000000000000000000000000000000..819cad4d92a379a3c7392acb6e6a855f97a32f02 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/constant/Const.java @@ -0,0 +1,90 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.constant; + +/** + * HmSounder Const + * + * @since 2021-01-17 + */ +public class Const { + /** + * -1 + */ + public static final int NUMBER_NEGATIVE_1 = -1; + /** + * 100 + */ + public static final int NUMBER_100 = 100; + /** + * 60 + */ + public static final int NUMBER_60 = 60; + /** + * 114 + */ + public static final int NUMBER_114 = 114; + /** + * 300 + */ + public static final int NUMBER_300 = 300; + /** + * 500 + */ + public static final int NUMBER_500 = 500; + /** + * BUFFERSIZE + */ + public static final int BUFFERSIZE = 1024; + + /** + * SAMPLE RATE + */ + public static final int SAMPLE_RATE = 44100; + + /** + * BUFFER SIZE IN BYTES + */ + public static final int BUFFER_SIZE_IN_BYTES = 100; + + /** + * VOICE FILE PREFIX + */ + public static final String VOICE_FILE_PREFIX = "VID_"; + + /** + * VOICE FILE PREFIX + */ + public static final String VOICE_FILE_MUSIC = "MUSIC_"; + + /** + * VOICE FILE NAME + */ + public static final String VOICE_FILE_NAME = "test"; + + /** + * VOICE FILE TYPE + */ + public static final String VOICE_FILE_TYPE_MP3 = ".mp3"; + + /** + * VOICE FILE TYPE + */ + public static final String VOICE_FILE_TYPE_M4A = ".m4a"; + + private Const() { + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/AudioRecorder.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/AudioRecorder.java new file mode 100644 index 0000000000000000000000000000000000000000..cae4e517fd3566544c991a7952293f5aeb7944a5 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/AudioRecorder.java @@ -0,0 +1,203 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.media; + +import com.huawei.harmonyaudiodemo.constant.Const; +import com.huawei.harmonyaudiodemo.media.api.AudioRecordListener; +import com.huawei.harmonyaudiodemo.media.constant.MediaConst; +import com.huawei.harmonyaudiodemo.util.LogUtil; + +import ohos.agp.utils.TextTool; +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.media.audio.AudioCapturer; +import ohos.media.audio.AudioCapturerInfo; +import ohos.media.audio.AudioStreamInfo; + +import java.io.BufferedOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * Hm AudioRecorder + * + * @since 2021-04-04 + */ +public class AudioRecorder { + private static final String TAG = AudioRecorder.class.getSimpleName(); + private AudioCapturer audioCapturer; + private AudioStreamInfo audioStreamInfo; + private EventHandler audioRecorderHandler; + private Builder builder; + private int bufferSize; + private boolean isRecording; + private boolean isSaveFile; + + private AudioRecordListener audioRecordListener; + + private AudioRecorder(Builder builder) { + this.builder = builder; + isSaveFile = !TextTool.isNullOrEmpty(builder.savefilePath); + bufferSize = + AudioCapturer.getMinBufferSize( + builder.inputSampleRate, + AudioStreamInfo.getChannelCount(builder.channelMask), + builder.encodingFormat.getValue()); + audioRecorderHandler = new EventHandler(EventRunner.create(AudioRecorder.class.getSimpleName())); + initRecord(); + } + + private void initRecord() { + if (audioStreamInfo == null) { + audioStreamInfo = new AudioStreamInfo.Builder() + .encodingFormat(builder.encodingFormat) + .channelMask(builder.channelMask) + .sampleRate(builder.inputSampleRate) + .build(); + AudioCapturerInfo audioCapturerInfo = new AudioCapturerInfo.Builder() + .audioStreamInfo(audioStreamInfo) + .audioInputSource(builder.inputSource) + .build(); + audioCapturer = new AudioCapturer(audioCapturerInfo); + } + } + + private void startRecord() { + isRecording = true; + BufferedOutputStream dos = null; + try { + if (isSaveFile) { + dos = new BufferedOutputStream(new FileOutputStream(builder.savefilePath)); + } + byte[] buffers = new byte[bufferSize]; + int length = audioCapturer.read(buffers, 0, bufferSize); + while (length != Const.NUMBER_NEGATIVE_1) { + if (audioRecordListener != null) { + audioRecordListener.onGetRecordBuffer(buffers, length); + } + if (dos != null) { + dos.write(buffers); + } + length = audioCapturer.read(buffers, 0, bufferSize); + } + } catch (IOException e) { + LogUtil.error(TAG, "start record failed!"); + } finally { + if (dos != null) { + try { + dos.close(); + } catch (IOException e) { + LogUtil.error(TAG, "start record failed!"); + } + } + } + } + + /** + * record + */ + public void record() { + if (!isRecording) { + initRecord(); + audioRecorderHandler.postTask(() -> { + if (audioCapturer.start()) { + startRecord(); + } + }); + } + } + + /** + * stopRecord + */ + public void stopRecord() { + if (isRecording && audioCapturer.stop()) { + isRecording = false; + } + } + + /** + * setAudioRecordListener + * + * @param listener listener + */ + public void setAudioRecordListener(AudioRecordListener listener) { + audioRecordListener = listener; + } + + /** + * release recorder + */ + public void release() { + stopRecord(); + if (audioCapturer != null) { + audioCapturer.release(); + } + audioStreamInfo = null; + } + + /** + * is recording in current time + * + * @return isRecording + */ + public boolean isRecording() { + return isRecording; + } + + /** + * Builder + * + * @since 2020-12-04 + */ + public static class Builder { + private String savefilePath; + private AudioStreamInfo.EncodingFormat encodingFormat; + private AudioStreamInfo.ChannelMask channelMask; + private AudioCapturerInfo.AudioInputSource inputSource; + private int inputSampleRate; + + /** + * constructor of Builder + */ + public Builder() { + encodingFormat = AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT; // 16-bit PCM + channelMask = AudioStreamInfo.ChannelMask.CHANNEL_IN_STEREO; // 双声道 + inputSource = AudioCapturerInfo.AudioInputSource.AUDIO_INPUT_SOURCE_VOICE_COMMUNICATION; // 消除回声,降噪 + inputSampleRate = MediaConst.SAMPLE_RATE; + } + + /** + * setSaveFilePath of Builder + * + * @param filePath filePath + * @return builder + */ + public Builder setSaveFilePath(String filePath) { + this.savefilePath = filePath; + return this; + } + + /** + * create of Builder + * + * @return AudioRecorder + */ + public AudioRecorder create() { + return new AudioRecorder(this); + } + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/AudioRender.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/AudioRender.java new file mode 100644 index 0000000000000000000000000000000000000000..d45b76e6c97c4ad2656e7bb1432971cbdf70713e --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/AudioRender.java @@ -0,0 +1,226 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.media; + +import com.huawei.harmonyaudiodemo.media.api.AudioPlayListener; +import com.huawei.harmonyaudiodemo.media.constant.MediaConst; +import com.huawei.harmonyaudiodemo.media.constant.MediaStatu; + +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.media.audio.AudioCapturer; +import ohos.media.audio.AudioRenderer; +import ohos.media.audio.AudioRendererInfo; +import ohos.media.audio.AudioStreamInfo; + +/** + * AudioRender + * + * @since 2021-04-09 + */ +public class AudioRender { + private static final String TAG = AudioRender.class.getSimpleName(); + private AudioRendererInfo audioRenderInfo; + private AudioRenderer audioRender; + private EventHandler audioRenderHandler; + private MediaStatu audioRenderStatu = MediaStatu.IDEL; + private Builder builder; + private int bufferSize; + private AudioPlayListener audioPlayListener; + + private AudioRender(Builder builder) { + this.builder = builder; + bufferSize = + AudioCapturer.getMinBufferSize( + builder.inputSampleRate, + AudioStreamInfo.getChannelCount(builder.channelMask), + builder.encodingFormat.getValue()); + audioRenderHandler = new EventHandler(EventRunner.create(AudioRender.class.getSimpleName())); + initRender(); + } + + private void initRender() { + AudioStreamInfo asi = new AudioStreamInfo.Builder() + .encodingFormat(builder.encodingFormat) + .channelMask(builder.channelMask) + .sampleRate(builder.inputSampleRate) + .audioStreamFlag(builder.streamFlag) + .streamUsage(builder.streamUsage) + .build(); + audioRenderInfo = new AudioRendererInfo.Builder() + .audioStreamInfo(asi) + .audioStreamOutputFlag(builder.streamOutputFlag) + .bufferSizeInBytes(bufferSize) + .isOffload(builder.isOneOffLoad) // false表示分段传输buffer并播放,true表示整个音频流一次性传输到HAL层播放 + .build(); + audioRender = new AudioRenderer(audioRenderInfo, AudioRenderer.PlayMode.MODE_STREAM); + audioRender.setFrameIntervalObserver(() -> { + if (audioRender.getAudioTime().getFramePosition() != 0) { + if (audioPlayListener != null) { + audioPlayListener.onComplete(); + } + release(); + } + }, MediaConst.READ_RENDER_INTERVAL, audioRenderHandler); + } + + /** + * start + */ + public void start() { + if (audioRenderStatu == MediaStatu.STOP || audioRenderStatu == MediaStatu.IDEL) { + if (audioRender != null) { + if (audioRender.start()) { + audioRenderStatu = MediaStatu.START; + } + } + } + } + + /** + * pause + */ + public void pause() { + if (audioRender != null) { + if (audioRender.pause()) { + audioRenderStatu = MediaStatu.PAUSE; + } + } + } + + /** + * setSpeed + * + * @param speed speed + */ + public void setSpeed(float speed) { + if (audioRender != null) { + audioRender.setSpeed(speed); + } + } + + /** + * setVolume + * + * @param volume volume + */ + public void setVolume(float volume) { + if (audioRender != null) { + audioRender.setVolume(volume); + } + } + + /** + * stop + */ + public void stop() { + if (audioRender != null) { + if (audioRender.stop()) { + audioRenderStatu = MediaStatu.STOP; + if (audioPlayListener != null) { + audioPlayListener.onComplete(); + } + } + } + } + + /** + * playRecord + * + * @param bytes bytes + * @param length length + */ + public void play(byte[] bytes, int length) { + if (audioRenderInfo == null) { + initRender(); + } + start(); + audioRenderHandler.postTask(() -> { + byte[] datas = new byte[length]; + System.arraycopy(bytes, 0, datas, 0, datas.length); + audioRender.write(datas, 0, datas.length); + }); + } + + /** + * release recorder + */ + public void release() { + if (audioRender != null) { + if (audioRender.release()) { + audioRenderStatu = MediaStatu.IDEL; + audioRenderInfo = null; + } + } + } + + /** + * release recorder + * + * @param listener listener + */ + public void setPlayListener(AudioPlayListener listener) { + audioPlayListener = listener; + } + + /** + * Builder + * + * @since 2020-12-04 + */ + public static class Builder { + private boolean isOneOffLoad; + private AudioStreamInfo.EncodingFormat encodingFormat; + private AudioStreamInfo.ChannelMask channelMask; + private int inputSampleRate; + private AudioStreamInfo.AudioStreamFlag streamFlag; + private AudioStreamInfo.StreamUsage streamUsage; + private AudioRendererInfo.AudioStreamOutputFlag streamOutputFlag; + + /** + * constructor of Builder + */ + public Builder() { + isOneOffLoad = true; + encodingFormat = AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT; // 16-bit PCM + channelMask = AudioStreamInfo.ChannelMask.CHANNEL_OUT_STEREO; // 双声道 + inputSampleRate = MediaConst.SAMPLE_RATE; + streamFlag = AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_MAY_DUCK; // 混音 + streamUsage = AudioStreamInfo.StreamUsage.STREAM_USAGE_MEDIA; // 媒体类音频 + streamOutputFlag = AudioRendererInfo.AudioStreamOutputFlag.AUDIO_STREAM_OUTPUT_FLAG_DIRECT_PCM; + } + + /** + * setOneOffLoad of Builder + * + * @param isOneOffLoadDatas isOneOffLoad + * @return builder + */ + public Builder setOneOffLoad(boolean isOneOffLoadDatas) { + this.isOneOffLoad = isOneOffLoadDatas; + return this; + } + + /** + * create of Builder + * + * @return AudioRender + */ + public AudioRender create() { + return new AudioRender(this); + } + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/api/AudioPlayListener.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/api/AudioPlayListener.java new file mode 100644 index 0000000000000000000000000000000000000000..12981f05636407cd326bfaee04f11324e0aa5509 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/api/AudioPlayListener.java @@ -0,0 +1,28 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.media.api; + +/** + * AudioPlayListener + * + * @since 2021-04-09 + */ +public interface AudioPlayListener { + /** + * onComplete + */ + void onComplete(); +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/api/AudioRecordListener.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/api/AudioRecordListener.java new file mode 100644 index 0000000000000000000000000000000000000000..bb9111a6c83031cf271878846c60bf60281a2870 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/api/AudioRecordListener.java @@ -0,0 +1,31 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.media.api; + +/** + * AudioRecordListener + * + * @since 2021-04-09 + */ +public interface AudioRecordListener { + /** + * onGetRecordBuffer + * + * @param length length + * @param buffer buffer + */ + void onGetRecordBuffer(byte[] buffer, int length); +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/constant/MediaConst.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/constant/MediaConst.java new file mode 100644 index 0000000000000000000000000000000000000000..a586540651ca5624acd72bc09783895f69c8d162 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/constant/MediaConst.java @@ -0,0 +1,65 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.media.constant; + +/** + * Camera ConstUtil + * + * @since 2021-01-17 + */ +public class MediaConst { + /** + * read render interval + */ + public static final int READ_RENDER_INTERVAL = 1024; + /** + * VOICE FILE PREFIX + */ + public static final String VOICE_FILE_MUSIC = "MUSIC_"; + + /** + * VOICE FILE TYPE + */ + public static final String VOICE_FILE_TYPE_MP3 = ".mp3"; + + /** + * recorder fps + */ + public static final int RECORDER_FPS = 30; + + /** + * recorder bit rate + */ + public static final int RECORDER_BIT_RATE = 10000000; + + /** + * recorder frame rate + */ + public static final int RECORDER_FRAME_RATE = 25; + + /** + * BUFFERSIZE + */ + public static final int BUFFERSIZE = 1024; + + /** + * SAMPLE RATE + */ + public static final int SAMPLE_RATE = 44100; + + private MediaConst() { + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/constant/MediaStatu.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/constant/MediaStatu.java new file mode 100644 index 0000000000000000000000000000000000000000..c4e856c98fb803de11f7e1e65df1d6958f943417 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/media/constant/MediaStatu.java @@ -0,0 +1,44 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.media.constant; + +/** + * PlayerStatu enum + * + * @since 2021-04-04 + */ +public enum MediaStatu { + /** + * idel + */ + IDEL, + /** + * preparing + */ + PREPARED, + /** + * start + */ + START, + /** + * pause + */ + PAUSE, + /** + * stop + */ + STOP +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/HmPlayer.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/HmPlayer.java new file mode 100644 index 0000000000000000000000000000000000000000..02c7f88e03acf7c9e1fc2474542207884d270f04 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/HmPlayer.java @@ -0,0 +1,505 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player; + +import com.huawei.harmonyaudiodemo.constant.Const; +import com.huawei.harmonyaudiodemo.player.api.ImplHmPlayer; +import com.huawei.harmonyaudiodemo.player.api.ImplLifecycle; +import com.huawei.harmonyaudiodemo.player.api.ScreenChangeListener; +import com.huawei.harmonyaudiodemo.player.api.StatuChangeListener; +import com.huawei.harmonyaudiodemo.player.constant.PlayerStatu; +import com.huawei.harmonyaudiodemo.player.factory.SourceFactory; +import com.huawei.harmonyaudiodemo.player.manager.HmPlayerLifecycle; +import com.huawei.harmonyaudiodemo.util.LogUtil; + +import ohos.agp.graphics.Surface; +import ohos.app.Context; +import ohos.app.dispatcher.task.TaskPriority; +import ohos.media.common.Source; +import ohos.media.player.Player; + +import java.util.ArrayList; +import java.util.List; + +/** + * Hm player + * + * @since 2021-04-04 + */ +public class HmPlayer implements ImplHmPlayer { + private static final String TAG = HmPlayer.class.getSimpleName(); + private static final int MICRO_MILLI_RATE = 1000; + private Player mPlayer; + private Surface surface; + private HmPlayerLifecycle mLifecycle; + private Builder mBuilder; + private PlayerStatu mStatu = PlayerStatu.IDEL; + private float currentVolume = 1; + private double videoScale = Const.NUMBER_NEGATIVE_1; + private boolean isGestureOpen = true; + + private List statuChangeCallbacks = new ArrayList<>(0); + private List screenChangeCallbacks = new ArrayList<>(0); + + /** + * constructor of HmPlayer + * + * @param builder builder + */ + private HmPlayer(Builder builder) { + mBuilder = builder; + mLifecycle = new HmPlayerLifecycle(this); + } + + private void initBasePlayer() { + mPlayer = new Player(mBuilder.mContext); + Source source = new SourceFactory(mBuilder.mContext, mBuilder.filePath).getSource(); + mPlayer.setSource(source); + mPlayer.setPlayerCallback(new HmPlayerCallback()); + } + + /** + * HmPlayer Callback + * + * @since 2020-12-04 + */ + private class HmPlayerCallback implements Player.IPlayerCallback { + @Override + public void onPrepared() { + LogUtil.info(TAG, "onPrepared is called "); + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PREPARED; + callback.statuCallback(PlayerStatu.PREPARED); + } + } + + @Override + public void onMessage(int info, int i1) { + LogUtil.info(TAG, "onMessage info is " + info + ",i1 is" + i1); + if (i1 == 0) { + switch (info) { + case Player.PLAYER_INFO_VIDEO_RENDERING_START: + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PLAY; + callback.statuCallback(PlayerStatu.PLAY); + } + if (mBuilder.isPause) { + pause(); + } + break; + case Player.PLAYER_INFO_BUFFERING_START: + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.BUFFERING; + callback.statuCallback(PlayerStatu.BUFFERING); + } + break; + case Player.PLAYER_INFO_BUFFERING_END: + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PLAY; + callback.statuCallback(PlayerStatu.PLAY); + } + break; + default: + break; + } + } + } + + @Override + public void onError(int type, int extra) { + LogUtil.info(TAG, "onError is called ,i is " + type + ",i1 is " + extra); + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.ERROR; + callback.statuCallback(PlayerStatu.ERROR); + } + release(); + } + + @Override + public void onResolutionChanged(int videoX, int videoY) { + LogUtil.info(TAG, "onResolutionChanged videoX is " + videoX + ",videoY is " + videoY); + if (!mBuilder.isStretch && videoX != 0 && videoY != 0) { + videoScale = (double) videoX / videoY; + for (ScreenChangeListener screenChangeCallback : screenChangeCallbacks) { + screenChangeCallback.screenCallback(0, 0); + } + } + } + + @Override + public void onPlayBackComplete() { + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.COMPLETE; + callback.statuCallback(PlayerStatu.COMPLETE); + } + } + + @Override + public void onRewindToComplete() { + resume(); + } + + @Override + public void onBufferingChange(int value) { + } + + @Override + public void onNewTimedMetaData(Player.MediaTimedMetaData mediaTimedMetaData) { + } + + @Override + public void onMediaTimeIncontinuity(Player.MediaTimeInfo mediaTimeInfo) { + LogUtil.info(TAG, "onMediaTimeIncontinuity is called"); + for (Player.StreamInfo streanInfo : mPlayer.getStreamInfo()) { + int streamType = streanInfo.getStreamType(); + if (streamType == Player.StreamInfo.MEDIA_STREAM_TYPE_AUDIO && mStatu == PlayerStatu.PREPARED) { + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PLAY; + callback.statuCallback(PlayerStatu.PLAY); + } + if (mBuilder.isPause) { + pause(); + } + } + } + } + } + + /** + * start time consuming operation + */ + private void start() { + if (mPlayer != null) { + mBuilder.mContext.getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(() -> { + if (surface != null) { + mPlayer.setVideoSurface(surface); + } else { + LogUtil.error(TAG, "The surface has not been initialized."); + } + mPlayer.prepare(); + if (mBuilder.startMillisecond > 0) { + int microsecond = mBuilder.startMillisecond * MICRO_MILLI_RATE; + mPlayer.rewindTo(microsecond); + } + mPlayer.play(); + }); + } + } + + @Override + public ImplLifecycle getLifecycle() { + return mLifecycle; + } + + @Override + public void addSurface(Surface videoSurface) { + this.surface = videoSurface; + } + + @Override + public void addPlayerStatuCallback(StatuChangeListener callback) { + if (callback != null) { + statuChangeCallbacks.add(callback); + } + } + + @Override + public void removePlayerStatuCallback(StatuChangeListener callback) { + statuChangeCallbacks.remove(callback); + } + + @Override + public void addPlayerViewCallback(ScreenChangeListener callback) { + if (callback != null) { + screenChangeCallbacks.add(callback); + } + } + + @Override + public void removePlayerViewCallback(ScreenChangeListener callback) { + screenChangeCallbacks.remove(callback); + } + + @Override + public Builder getBuilder() { + return mBuilder; + } + + @Override + public PlayerStatu getPlayerStatu() { + return mStatu; + } + + @Override + public void resizeScreen(int width, int height) { + for (ScreenChangeListener screenChangeCallback : screenChangeCallbacks) { + screenChangeCallback.screenCallback(width, height); + } + } + + @Override + public void gestureSwitch(boolean isOpen) { + isGestureOpen = isOpen; + } + + @Override + public boolean isGestureOpen() { + return isGestureOpen; + } + + @Override + public void play() { + if (mPlayer != null) { + mPlayer.reset(); + } + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PREPARING; + callback.statuCallback(PlayerStatu.PREPARING); + } + initBasePlayer(); + start(); + } + + @Override + public void replay() { + if (isPlaying()) { + rewindTo(0); + } else { + reload(mBuilder.filePath, 0); + } + } + + @Override + public void reload(String filepath, int startMillisecond) { + mBuilder.filePath = filepath; + mBuilder.startMillisecond = startMillisecond; + play(); + } + + @Override + public void stop() { + if (mPlayer == null) { + return; + } + mPlayer.stop(); + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.STOP; + callback.statuCallback(PlayerStatu.STOP); + } + } + + @Override + public void release() { + if (mPlayer == null) { + return; + } + if (mStatu != PlayerStatu.IDEL) { + videoScale = Const.NUMBER_NEGATIVE_1; + mPlayer.release(); + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.IDEL; + callback.statuCallback(PlayerStatu.IDEL); + } + } + } + + @Override + public void resume() { + if (mPlayer == null) { + return; + } + if (mStatu != PlayerStatu.IDEL) { + if (!isPlaying()) { + mPlayer.play(); + } + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PLAY; + callback.statuCallback(PlayerStatu.PLAY); + } + } + } + + @Override + public void pause() { + if (mPlayer == null) { + return; + } + if (isPlaying()) { + mPlayer.pause(); + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PAUSE; + callback.statuCallback(PlayerStatu.PAUSE); + } + } + } + + @Override + public int getCurrentPosition() { + if (mPlayer == null) { + return 0; + } + return mPlayer.getCurrentTime(); + } + + @Override + public int getDuration() { + if (mPlayer == null) { + return 0; + } + return mPlayer.getDuration(); + } + + @Override + public float getVolume() { + return currentVolume; + } + + @Override + public void setVolume(float volume) { + if (mPlayer != null && mPlayer.setVolume(volume)) { + currentVolume = volume; + } + } + + @Override + public void setPlaySpeed(float speed) { + if (mPlayer == null) { + return; + } + if (mStatu != PlayerStatu.IDEL) { + mPlayer.setPlaybackSpeed(speed); + } + } + + @Override + public double getVideoScale() { + return videoScale; + } + + @Override + public boolean isPlaying() { + return mPlayer.isNowPlaying(); + } + + @Override + public void rewindTo(int startMicrosecond) { + if (mPlayer == null) { + return; + } + if (mStatu != PlayerStatu.IDEL) { + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.BUFFERING; + callback.statuCallback(PlayerStatu.BUFFERING); + } + mPlayer.rewindTo(startMicrosecond * MICRO_MILLI_RATE); + } + } + + /** + * Builder + * + * @since 2020-12-04 + */ + public static class Builder { + private Context mContext; + private String filePath; + private int startMillisecond; + private boolean isStretch; + private boolean isPause; + + /** + * constructor of Builder + * + * @param context context + */ + public Builder(Context context) { + mContext = context; + filePath = ""; + startMillisecond = 0; + } + + /** + * setFilePath of Builder + * + * @param filePath filePath + * @return builder + */ + public Builder setFilePath(String filePath) { + this.filePath = filePath; + return this; + } + + /** + * getFilePath of Builder + * + * @return filePath + */ + public String getFilePath() { + return filePath; + } + + /** + * setStartMillisecond of Builder + * + * @param startMillisecond startMillisecond + * @return builder + */ + public Builder setStartMillisecond(int startMillisecond) { + this.startMillisecond = startMillisecond; + return this; + } + + /** + * getStartMillisecond of Builder + * + * @return startMillisecond + */ + public int getStartMillisecond() { + return startMillisecond; + } + + /** + * setStretch of Builder + * + * @param isS isStretch + * @return Builder + */ + public Builder setStretch(boolean isS) { + this.isStretch = isS; + return this; + } + + /** + * setPause of Builder + * + * @param isP isPause + * @return Builder + */ + public Builder setPause(boolean isP) { + this.isPause = isP; + return this; + } + + /** + * create of Builder + * + * @return IPlayer + */ + public ImplHmPlayer create() { + return new HmPlayer(this); + } + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/HmPlayModuler.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/HmPlayModuler.java new file mode 100644 index 0000000000000000000000000000000000000000..b019323005100927bf5f5d6ef892c390579d14d3 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/HmPlayModuler.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.api; + +/** + * IPlayModuler + * + * @since 2021-04-09 + * + */ +public interface HmPlayModuler { + /** + * bind + * + * @param player player + */ + void bind(ImplHmPlayer player); + + /** + * unbind + * + */ + void unbind(); +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/ImplHmPlayer.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/ImplHmPlayer.java new file mode 100644 index 0000000000000000000000000000000000000000..832f4bc427d0d31fcaee8b5ef7e0e458a83985d2 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/ImplHmPlayer.java @@ -0,0 +1,200 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.api; + +import com.huawei.harmonyaudiodemo.player.HmPlayer; +import com.huawei.harmonyaudiodemo.player.constant.PlayerStatu; + +import ohos.agp.graphics.Surface; + +/** + * IPlayer interface + * + * @since 2021-04-04 + */ +public interface ImplHmPlayer { + /** + * addSurface + * + * @param surface surface + */ + void addSurface(Surface surface); + + /** + * addPlayerStatuCallback + * + * @param callback callback + */ + void addPlayerStatuCallback(StatuChangeListener callback); + + /** + * removePlayerStatuCallback + * + * @param callback callback + */ + void removePlayerStatuCallback(StatuChangeListener callback); + + /** + * addPlayerViewCallback + * + * @param callback callback + */ + void addPlayerViewCallback(ScreenChangeListener callback); + + /** + * removePlayerViewCallback + * + * @param callback callback + */ + void removePlayerViewCallback(ScreenChangeListener callback); + + /** + * play + */ + void play(); + + /** + * replay + */ + void replay(); + + /** + * reload + * + * @param filepath filepath + * @param startMillisecond startMillisecond + */ + void reload(String filepath, int startMillisecond); + + /** + * resume + */ + void resume(); + + /** + * pause + */ + void pause(); + + /** + * getCurrentPosition + * + * @return current position + */ + int getCurrentPosition(); + + /** + * getDuration + * + * @return duration + */ + int getDuration(); + + /** + * getVolume + * + * @return float + */ + float getVolume(); + + /** + * set play volume + * + * @param volume 0~1 + */ + void setVolume(float volume); + + /** + * set play speed + * + * @param speed 0~12 + */ + void setPlaySpeed(float speed); + + /** + * getVideoScale + * + * @return double + */ + double getVideoScale(); + + /** + * rewindTo + * + * @param startMicrosecond startMicrosecond(ms) + */ + void rewindTo(int startMicrosecond); + + /** + * isPlaying + * + * @return isPlaying + */ + boolean isPlaying(); + + /** + * stop + */ + void stop(); + + /** + * release + */ + void release(); + + /** + * getLifecycle + * + * @return ImplLifecycle + */ + ImplLifecycle getLifecycle(); + + /** + * getBuilder + * + * @return Builder + */ + HmPlayer.Builder getBuilder(); + + /** + * getPlayerStatu + * + * @return PlayerStatu + */ + PlayerStatu getPlayerStatu(); + + /** + * resizeScreen + * + * @param width width + * @param height height + */ + void resizeScreen(int width, int height); + + /** + * openGesture + * + * @param isOpen isOpen + */ + void gestureSwitch(boolean isOpen); + + /** + * openGesture + * + * @return isGestureOpen + */ + boolean isGestureOpen(); +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/ImplLifecycle.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/ImplLifecycle.java new file mode 100644 index 0000000000000000000000000000000000000000..709f0bd45da46d51f5c59fd31480926753353630 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/ImplLifecycle.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.api; + +/** + * ImplLifecycle + * + * @since 2021-04-09 + * + */ +public interface ImplLifecycle { + /** + * onStart + * + */ + void onStart(); + + /** + * onForeground + * + */ + void onForeground(); + + /** + * onBackground + * + */ + void onBackground(); + + /** + * onStop + * + */ + void onStop(); +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/ScreenChangeListener.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/ScreenChangeListener.java new file mode 100644 index 0000000000000000000000000000000000000000..5da18584ecabf6d633f139002a35e470f39ed521 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/ScreenChangeListener.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.api; + +/** + * ScreenChangeListener interface + * + * @since 2021-04-04 + * + */ +public interface ScreenChangeListener { + /** + * screenCallback + * + * @param width width + * @param height height + */ + void screenCallback(int width, int height); +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/StatuChangeListener.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/StatuChangeListener.java new file mode 100644 index 0000000000000000000000000000000000000000..9ee167fc4ef0c3818a9a7d6c593c6b3be4758686 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/api/StatuChangeListener.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.api; + +import com.huawei.harmonyaudiodemo.player.constant.PlayerStatu; + +/** + * StatuChangeListener interface + * + * @since 2021-04-04 + * + */ +public interface StatuChangeListener { + /** + * statuCallback + * + * @param statu statu + */ + void statuCallback(PlayerStatu statu); +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/constant/Constants.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/constant/Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..6545705d03aa217639657b49084cba98fd910949 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/constant/Constants.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.constant; + +/** + * Constants + * + * @since 2021-04-04 + */ +public class Constants { + /** + * running + */ + public static final int PLAYER_PROGRESS_RUNNING = 0; + /** + * hide + */ + public static final int PLAYER_CONTROLLER_HIDE = 1; + /** + * hide + */ + public static final int PLAYER_CONTROLLER_SHOW = 2; + /** + * 100 + */ + public static final int ONE_HUNDRED_PERCENT = 100; + /** + * rewind step + */ + public static final int REWIND_STEP = 5000; + /** + * volume step + */ + public static final int VOLUME_STEP = 5; + /** + * INTENT STARTTIME PARAM + */ + public static final String INTENT_STARTTIME_PARAM = "intetn_starttime_param"; + /** + * INTENT PLAYURL PARAM + */ + public static final String INTENT_PLAYURL_PARAM = "intetn_playurl_param"; + /** + * INTENT PLAYSTATU PARAM + */ + public static final String INTENT_PLAYSTATU_PARAM = "intetn_playstatu_param"; + /** + * INTENT LANDSCREEN REQUEST CODE + */ + public static final int INTENT_LANDSCREEN_REQUEST_CODE = 1001; + + private Constants() { + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/constant/PlayerStatu.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/constant/PlayerStatu.java new file mode 100644 index 0000000000000000000000000000000000000000..55dd7eae74793b8527c046362b697d915bd63a1f --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/constant/PlayerStatu.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.constant; + +/** + * PlayerStatu enum + * + * @since 2021-04-04 + * + */ +public enum PlayerStatu { + /** + * idel + * + */ + IDEL, + /** + * preparing + * + */ + PREPARING, + /** + * prepared + * + */ + PREPARED, + /** + * play + * + */ + PLAY, + /** + * pause + * + */ + PAUSE, + /** + * stop + * + */ + STOP, + /** + * complete + * + */ + COMPLETE, + /** + * error + * + */ + ERROR, + /** + * buffering + * + */ + BUFFERING +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/factory/SourceFactory.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/factory/SourceFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..22597d7b0b96de58133d4ebe60bacfc6b7d30a43 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/factory/SourceFactory.java @@ -0,0 +1,87 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.factory; + +import com.huawei.harmonyaudiodemo.util.LogUtil; + +import ohos.app.Context; +import ohos.global.resource.RawFileDescriptor; +import ohos.media.common.Source; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; + +/** + * SourceFactory + * + * @since 2021-04-04 + * + */ +public class SourceFactory { + private static final String TAG = "SourceFactory"; + private static final String NET_HTTP_MATCH = "http"; + private static final String NET_RTMP_MATCH = "rtmp"; + private static final String NET_RTSP_MATCH = "rtsp"; + private static final String STORAGE_MATCH = "/storage/"; + + private Source mPlayerSource; + + /** + * constructor of SourceFactory + * + * @param context context + * @param path path + */ + public SourceFactory(Context context, String path) { + try { + initSourceType(context, path); + } catch (IOException e) { + LogUtil.error(TAG, "Audio resource is unavailable: "); + } + } + + private void initSourceType(Context context, String path) throws IOException { + if (context == null || path == null) { + return; + } + if (path.substring(0, NET_HTTP_MATCH.length()).equalsIgnoreCase(NET_HTTP_MATCH) + || path.substring(0, NET_RTMP_MATCH.length()).equalsIgnoreCase(NET_RTMP_MATCH) + || path.substring(0, NET_RTSP_MATCH.length()).equalsIgnoreCase(NET_RTSP_MATCH)) { + mPlayerSource = new Source(path); + } else if (path.startsWith(STORAGE_MATCH)) { + File file = new File(path); + if (file.exists()) { + FileInputStream fileInputStream = new FileInputStream(file); + FileDescriptor fileDescriptor = fileInputStream.getFD(); + mPlayerSource = new Source(fileDescriptor); + } + } else { + RawFileDescriptor fd = context.getResourceManager().getRawFileEntry(path).openRawFileDescriptor(); + mPlayerSource = new Source(fd.getFileDescriptor(), fd.getStartPosition(), fd.getFileSize()); + } + } + + /** + * getSource + * + * @return Source Source + */ + public Source getSource() { + return mPlayerSource; + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/manager/HmPlayerLifecycle.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/manager/HmPlayerLifecycle.java new file mode 100644 index 0000000000000000000000000000000000000000..273021ca3cf00ab53bd58d9df05d8b8733c52067 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/manager/HmPlayerLifecycle.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.manager; + +import com.huawei.harmonyaudiodemo.player.api.ImplHmPlayer; +import com.huawei.harmonyaudiodemo.player.api.ImplLifecycle; +import com.huawei.harmonyaudiodemo.player.constant.PlayerStatu; + +/** + * HmPlayerLifecycle + * + * @since 2021-04-09 + * + */ +public class HmPlayerLifecycle implements ImplLifecycle { + private static final String TAG = HmPlayerLifecycle.class.getSimpleName(); + private ImplHmPlayer mPlayer; + + /** + * HmPlayerLifecycle + * + * @param player player + */ + public HmPlayerLifecycle(ImplHmPlayer player) { + mPlayer = player; + } + + @Override + public void onStart() { + } + + @Override + public void onForeground() { + String url = mPlayer.getBuilder().getFilePath(); + int startMillisecond = mPlayer.getBuilder().getStartMillisecond(); + mPlayer.reload(url, startMillisecond); + } + + @Override + public void onBackground() { + mPlayer.getBuilder().setPause(mPlayer.getPlayerStatu() == PlayerStatu.PAUSE); + mPlayer.getBuilder().setStartMillisecond(mPlayer.getCurrentPosition()); + mPlayer.release(); + } + + @Override + public void onStop() { + mPlayer.release(); + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/util/DateUtils.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/util/DateUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..f616b3565af0c8fd530a68ed0c552a308d3a62ae --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/util/DateUtils.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.util; + +import java.util.Locale; + +/** + * Date util + * + * @since 2021-04-04 + */ +public class DateUtils { + private static final int ONE_SECONDS_MS = 1000; + private static final int ONE_MINS_MINUTES = 60; + private static final int NUMBER = 16; + private static final String TIME_FORMAT = "%02d"; + private static final String SEMICOLON = ":"; + + private DateUtils() { + } + + /** + * conversion of msToString + * + * @param ms ms + * @return string + */ + public static String msToString(int ms) { + StringBuilder sb = new StringBuilder(NUMBER); + int seconds = ms / ONE_SECONDS_MS; + int minutes = seconds / ONE_MINS_MINUTES; + if (minutes > ONE_MINS_MINUTES) { + sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, minutes / ONE_MINS_MINUTES)); + sb.append(SEMICOLON); + sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, minutes % ONE_MINS_MINUTES)); + sb.append(SEMICOLON); + } else { + sb.append("00:"); + sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, minutes)); + sb.append(SEMICOLON); + } + + if (seconds > minutes * ONE_MINS_MINUTES) { + sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, seconds - minutes * ONE_MINS_MINUTES)); + } else { + sb.append("00"); + } + return sb.toString(); + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/view/PlayerLoading.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/view/PlayerLoading.java new file mode 100644 index 0000000000000000000000000000000000000000..71033b6c890195b584e1b92efb868510f5922ce7 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/view/PlayerLoading.java @@ -0,0 +1,149 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.view; + +import com.huawei.harmonyaudiodemo.ResourceTable; +import com.huawei.harmonyaudiodemo.player.api.HmPlayModuler; +import com.huawei.harmonyaudiodemo.player.api.ImplHmPlayer; + +import ohos.agp.animation.AnimatorProperty; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.components.Component.TouchEventListener; +import ohos.agp.components.ComponentContainer; +import ohos.agp.components.Image; +import ohos.agp.components.LayoutScatter; +import ohos.app.Context; +import ohos.multimodalinput.event.TouchEvent; + +/** + * PlayerLoading + * + * @since 2021-04-04 + */ +public class PlayerLoading extends ComponentContainer implements HmPlayModuler, TouchEventListener { + private static final int HALF_NUMBER = 2; + private static final int ANIM_ROTATE = 360; + private static final int ANIM_DURATION = 2000; + private static final int ANIM_LOOPED_COUNT = -1; + private ImplHmPlayer mPlayer; + private Image mLoading; + private AnimatorProperty mLoadingAnim; + + /** + * constructor of PlayerLoading + * + * @param context context + */ + public PlayerLoading(Context context) { + this(context, null); + } + + /** + * constructor of PlayerLoading + * + * @param context context + * @param attrSet attSet + */ + public PlayerLoading(Context context, AttrSet attrSet) { + this(context, attrSet, null); + } + + /** + * constructor of PlayerLoading + * + * @param context context + * @param attrSet attSet + * @param styleName styleName + */ + public PlayerLoading(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); + initView(context); + } + + private void initView(Context context) { + Component loadingContainer = + LayoutScatter.getInstance(context).parse(ResourceTable.Layout_player_loading_layout, null, false); + if (loadingContainer.findComponentById(ResourceTable.Id_image_loading) instanceof Image) { + mLoading = (Image) loadingContainer.findComponentById(ResourceTable.Id_image_loading); + initAnim(); + } + addComponent(loadingContainer); + hide(); + setTouchEventListener(this); + } + + private void initAnim() { + int with = mLoading.getWidth() / HALF_NUMBER; + int height = mLoading.getHeight() / HALF_NUMBER; + mLoading.setPivotX(with); + mLoading.setPivotY(height); + mLoadingAnim = mLoading.createAnimatorProperty(); + mLoadingAnim.rotate(ANIM_ROTATE).setDuration(ANIM_DURATION).setLoopedCount(ANIM_LOOPED_COUNT); + } + + private void initListener() { + mPlayer.addPlayerStatuCallback(statu -> mContext.getUITaskDispatcher().asyncDispatch(() -> { + switch (statu) { + case PREPARING: + case BUFFERING: + show(); + break; + case PLAY: + hide(); + break; + default: + break; + } + })); + } + + /** + * show of PlayerLoading + */ + public void show() { + if (mLoadingAnim.isPaused()) { + mLoadingAnim.resume(); + } else { + mLoadingAnim.start(); + } + setVisibility(VISIBLE); + } + + /** + * hide of PlayerLoading + */ + public void hide() { + setVisibility(INVISIBLE); + mLoadingAnim.pause(); + } + + @Override + public void bind(ImplHmPlayer player) { + mPlayer = player; + initListener(); + } + + @Override + public void unbind() { + mLoadingAnim.release(); + } + + @Override + public boolean onTouchEvent(Component component, TouchEvent touchEvent) { + return true; + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/view/SimplePlayerController.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/view/SimplePlayerController.java new file mode 100644 index 0000000000000000000000000000000000000000..3a066f32f6029ee18877c8d2c3bdde0df0637cf2 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/player/view/SimplePlayerController.java @@ -0,0 +1,314 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.player.view; + +import com.huawei.harmonyaudiodemo.ResourceTable; +import com.huawei.harmonyaudiodemo.player.api.HmPlayModuler; +import com.huawei.harmonyaudiodemo.player.api.ImplHmPlayer; +import com.huawei.harmonyaudiodemo.player.api.StatuChangeListener; +import com.huawei.harmonyaudiodemo.player.constant.Constants; +import com.huawei.harmonyaudiodemo.player.constant.PlayerStatu; +import com.huawei.harmonyaudiodemo.player.util.DateUtils; + +import ohos.agp.colors.RgbColor; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.components.ComponentContainer; +import ohos.agp.components.DependentLayout; +import ohos.agp.components.DirectionalLayout; +import ohos.agp.components.Image; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.Slider; +import ohos.agp.components.Text; +import ohos.agp.components.element.ShapeElement; +import ohos.app.Context; +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.eventhandler.InnerEvent; + +/** + * PlayerController + * + * @since 2021-04-04 + */ +public class SimplePlayerController extends ComponentContainer implements HmPlayModuler { + private static final int THUMB_RED = 255; + private static final int THUMB_GREEN = 255; + private static final int THUMB_BLUE = 240; + private static final int THUMB_WIDTH = 40; + private static final int THUMB_HEIGHT = 40; + private static final int THUMB_RADIUS = 20; + private static final int CONTROLLER_HIDE_DLEY_TIME = 5000; + private static final int PROGRESS_RUNNING_TIME = 1000; + private boolean mIsDragMode = false; + private Context mContext; + private ImplHmPlayer mPlayer; + private DependentLayout topLayout; + private DirectionalLayout bottomLayout; + private Image mBack; + private Image mPlayToogle; + private Image mForward; + private Image mBackward; + private Slider mProgressBar; + private Text mCurrentTime; + private Text mTotleTime; + private ControllerHandler mHandler; + private StatuChangeListener mStatuChangeListener = new StatuChangeListener() { + @Override + public void statuCallback(PlayerStatu statu) { + mContext.getUITaskDispatcher().asyncDispatch(() -> { + switch (statu) { + case PREPARING: + mPlayToogle.setClickable(false); + mProgressBar.setEnabled(false); + mProgressBar.setProgressValue(0); + break; + case PREPARED: + mProgressBar.setMaxValue(mPlayer.getDuration()); + mTotleTime.setText(DateUtils.msToString(mPlayer.getDuration())); + break; + case PLAY: + showController(false); + mPlayToogle.setPixelMap(ResourceTable.Media_ic_music_stop); + mPlayToogle.setClickable(true); + mProgressBar.setEnabled(true); + break; + case PAUSE: + mPlayToogle.setPixelMap(ResourceTable.Media_ic_music_play); + break; + case STOP: + case COMPLETE: + mPlayToogle.setPixelMap(ResourceTable.Media_ic_update); + mProgressBar.setEnabled(false); + break; + default: + break; + } + }); + } + }; + + /** + * constructor of SimplePlayerController + * + * @param context context + */ + public SimplePlayerController(Context context) { + this(context, null); + } + + /** + * constructor of SimplePlayerController + * + * @param context context + * @param attrSet attSet + */ + public SimplePlayerController(Context context, AttrSet attrSet) { + this(context, attrSet, null); + } + + /** + * constructor of SimplePlayerController + * + * @param context context + * @param attrSet attSet + * @param styleName styleName + */ + public SimplePlayerController(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); + mContext = context; + createHandler(); + initView(); + initListener(); + } + + private void createHandler() { + EventRunner runner = EventRunner.create(true); + if (runner == null) { + return; + } + mHandler = new ControllerHandler(runner); + } + + private void initView() { + Component playerController = + LayoutScatter.getInstance(mContext) + .parse(ResourceTable.Layout_simple_player_controller_layout, null, false); + addComponent(playerController); + if (playerController.findComponentById(ResourceTable.Id_controller_top_layout) instanceof DependentLayout) { + topLayout = (DependentLayout) playerController.findComponentById(ResourceTable.Id_controller_top_layout); + } + if (playerController.findComponentById(ResourceTable.Id_controller_bottom_layout) + instanceof DirectionalLayout) { + bottomLayout = (DirectionalLayout) playerController + .findComponentById(ResourceTable.Id_controller_bottom_layout); + } + if (playerController.findComponentById(ResourceTable.Id_back) instanceof Image) { + mBack = (Image) playerController.findComponentById(ResourceTable.Id_back); + } + if (playerController.findComponentById(ResourceTable.Id_play_controller) instanceof Image) { + mPlayToogle = (Image) playerController.findComponentById(ResourceTable.Id_play_controller); + } + if (playerController.findComponentById(ResourceTable.Id_play_forward) instanceof Image) { + mForward = (Image) playerController.findComponentById(ResourceTable.Id_play_forward); + } + if (playerController.findComponentById(ResourceTable.Id_play_backward) instanceof Image) { + mBackward = (Image) playerController.findComponentById(ResourceTable.Id_play_backward); + } + if (playerController.findComponentById(ResourceTable.Id_progress) instanceof Slider) { + mProgressBar = (Slider) playerController.findComponentById(ResourceTable.Id_progress); + } + ShapeElement shapeElement = new ShapeElement(); + shapeElement.setRgbColor(new RgbColor(THUMB_RED, THUMB_GREEN, THUMB_BLUE)); + shapeElement.setBounds(0, 0, THUMB_WIDTH, THUMB_HEIGHT); + shapeElement.setCornerRadius(THUMB_RADIUS); + mProgressBar.setThumbElement(shapeElement); + if (playerController.findComponentById(ResourceTable.Id_current_time) instanceof Text) { + mCurrentTime = (Text) playerController.findComponentById(ResourceTable.Id_current_time); + } + if (playerController.findComponentById(ResourceTable.Id_end_time) instanceof Text) { + mTotleTime = (Text) playerController.findComponentById(ResourceTable.Id_end_time); + } + } + + private void initListener() { + topLayout.setTouchEventListener((component, touchEvent) -> true); + bottomLayout.setTouchEventListener((component, touchEvent) -> true); + mBack.setClickedListener(component -> mContext.terminateAbility()); + } + + private void initPlayListener() { + mPlayer.addPlayerStatuCallback(mStatuChangeListener); + mPlayToogle.setClickedListener(component -> { + if (mPlayer.isPlaying()) { + mPlayer.pause(); + } else { + if (mPlayer.getPlayerStatu() == PlayerStatu.STOP) { + mPlayer.replay(); + } else { + mPlayer.resume(); + } + } + }); + mForward.setClickedListener(component -> + mPlayer.rewindTo(mPlayer.getCurrentPosition() + Constants.REWIND_STEP)); + mBackward.setClickedListener(component -> + mPlayer.rewindTo(mPlayer.getCurrentPosition() - Constants.REWIND_STEP)); + mProgressBar.setValueChangedListener( + new Slider.ValueChangedListener() { + @Override + public void onProgressUpdated(Slider slider, int value, boolean isB) { + mContext.getUITaskDispatcher().asyncDispatch(() -> + mCurrentTime.setText(DateUtils.msToString(value))); + } + + @Override + public void onTouchStart(Slider slider) { + mIsDragMode = true; + mHandler.removeEvent(Constants.PLAYER_PROGRESS_RUNNING, EventHandler.Priority.IMMEDIATE); + } + + @Override + public void onTouchEnd(Slider slider) { + mIsDragMode = false; + if (slider.getProgress() == mPlayer.getDuration()) { + mPlayer.stop(); + } else { + mPlayer.rewindTo(slider.getProgress()); + } + } + }); + } + + /** + * showController of PlayerController + * + * @param isAutoHide isAutoHide + */ + public void showController(boolean isAutoHide) { + mHandler.sendEvent(Constants.PLAYER_CONTROLLER_SHOW, EventHandler.Priority.HIGH); + if (isAutoHide) { + hideController(CONTROLLER_HIDE_DLEY_TIME); + } else { + mHandler.removeEvent(Constants.PLAYER_CONTROLLER_HIDE); + } + } + + /** + * hideController of PlayerController + * + * @param delay delay + */ + public void hideController(int delay) { + mHandler.removeEvent(Constants.PLAYER_CONTROLLER_HIDE); + mHandler.sendEvent(Constants.PLAYER_CONTROLLER_HIDE, delay, EventHandler.Priority.HIGH); + } + + @Override + public void bind(ImplHmPlayer player) { + mPlayer = player; + initPlayListener(); + } + + @Override + public void unbind() { + mHandler.removeAllEvent(); + mHandler = null; + } + + /** + * ControllerHandler + * + * @author chenweiquan + * @since 2020-12-04 + */ + private class ControllerHandler extends EventHandler { + private ControllerHandler(EventRunner runner) { + super(runner); + } + + @Override + public void processEvent(InnerEvent event) { + super.processEvent(event); + if (event == null) { + return; + } + switch (event.eventId) { + case Constants.PLAYER_PROGRESS_RUNNING: + if (mPlayer != null && mPlayer.isPlaying() && !mIsDragMode) { + mContext.getUITaskDispatcher().asyncDispatch(() -> { + mProgressBar.setProgressValue(mPlayer.getCurrentPosition()); + mCurrentTime.setText(DateUtils.msToString(mPlayer.getCurrentPosition())); + }); + mHandler.sendEvent( + Constants.PLAYER_PROGRESS_RUNNING, PROGRESS_RUNNING_TIME, Priority.IMMEDIATE); + } + break; + case Constants.PLAYER_CONTROLLER_HIDE: + mContext.getUITaskDispatcher().asyncDispatch(() -> setVisibility(INVISIBLE)); + mHandler.removeEvent(Constants.PLAYER_PROGRESS_RUNNING); + break; + case Constants.PLAYER_CONTROLLER_SHOW: + mHandler.removeEvent(Constants.PLAYER_PROGRESS_RUNNING); + mHandler.sendEvent(Constants.PLAYER_PROGRESS_RUNNING, Priority.IMMEDIATE); + mContext.getUITaskDispatcher().asyncDispatch(() -> setVisibility(VISIBLE)); + break; + default: + break; + } + } + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/MainAbilitySlice.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/MainAbilitySlice.java new file mode 100644 index 0000000000000000000000000000000000000000..9df0bbeafeebc8b220c22dec657b313d3f5eac1a --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/MainAbilitySlice.java @@ -0,0 +1,80 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.slice; + +import com.huawei.harmonyaudiodemo.MainAbility; +import com.huawei.harmonyaudiodemo.ResourceTable; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.aafwk.content.Operation; +import ohos.agp.components.Component; + +/** + * MainAbilitySlice + * + * @since 2021-04-04 + */ +public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener { + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_ability_main); + initView(); + } + + @Override + protected void onStop() { + super.onStop(); + } + + private void initView() { + findComponentById(ResourceTable.Id_sound_music_play_btn).setClickedListener(this); + findComponentById(ResourceTable.Id_sound_system_play_btn).setClickedListener(this); + findComponentById(ResourceTable.Id_sound_record_btn).setClickedListener(this); + findComponentById(ResourceTable.Id_sound_volume_btn).setClickedListener(this); + } + + @Override + public void onClick(Component view) { + Intent intent = new Intent(); + String actionName = ""; + switch (view.getId()) { + case ResourceTable.Id_sound_music_play_btn: + actionName = "action.sound.play.music"; + break; + case ResourceTable.Id_sound_system_play_btn: + actionName = "action.sound.play.system"; + break; + case ResourceTable.Id_sound_record_btn: + actionName = "action.sound.record"; + break; + case ResourceTable.Id_sound_volume_btn: + actionName = "action.sound.volume"; + break; + default: + break; + } + Operation operation = + new Intent.OperationBuilder() + .withBundleName(getBundleName()) + .withAbilityName(MainAbility.class.getName()) + .withAction(actionName) + .build(); + intent.setOperation(operation); + startAbility(intent); + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/MusicPlayerAbilitySlice.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/MusicPlayerAbilitySlice.java new file mode 100644 index 0000000000000000000000000000000000000000..388e039b32a556a6db484d3a588534dda736d0e8 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/MusicPlayerAbilitySlice.java @@ -0,0 +1,103 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.slice; + +import com.huawei.harmonyaudiodemo.ResourceTable; +import com.huawei.harmonyaudiodemo.constant.Const; +import com.huawei.harmonyaudiodemo.player.HmPlayer; +import com.huawei.harmonyaudiodemo.player.api.ImplHmPlayer; +import com.huawei.harmonyaudiodemo.player.view.PlayerLoading; +import com.huawei.harmonyaudiodemo.player.view.SimplePlayerController; +import com.huawei.harmonyaudiodemo.util.LogUtil; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.app.dispatcher.task.TaskPriority; +import ohos.global.resource.NotExistException; +import ohos.global.resource.WrongTypeException; + +import java.io.IOException; + +/** + * SimplePlayerAbilitySlice + * + * @since 2021-04-04 + */ +public class MusicPlayerAbilitySlice extends AbilitySlice { + private static final String TAG = MusicPlayerAbilitySlice.class.getSimpleName(); + private ImplHmPlayer player; + private PlayerLoading playerLoading; + private SimplePlayerController controllerView; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_ability_music_player); + try { + String mUrl = getResourceManager().getMediaPath(ResourceTable.Media_test); + player = new HmPlayer.Builder(this) + .setFilePath(mUrl) + .create(); + initView(); + getGlobalTaskDispatcher(TaskPriority.DEFAULT).delayDispatch(() -> player.play(), Const.NUMBER_100); + } catch (IOException | NotExistException | WrongTypeException e) { + LogUtil.error(TAG, "get media path failed!"); + } + } + + private void initView() { + if (findComponentById(ResourceTable.Id_loadint_view) instanceof PlayerLoading) { + playerLoading = (PlayerLoading) findComponentById(ResourceTable.Id_loadint_view); + } + if (findComponentById(ResourceTable.Id_controller_view) instanceof SimplePlayerController) { + controllerView = (SimplePlayerController) findComponentById(ResourceTable.Id_controller_view); + } + playerLoading.bind(player); + controllerView.bind(player); + } + + @Override + public void onActive() { + super.onActive(); + } + + @Override + protected void onInactive() { + LogUtil.info(TAG, "onInactive is called"); + super.onInactive(); + } + + @Override + public void onForeground(Intent intent) { + player.getLifecycle().onForeground(); + super.onForeground(intent); + } + + @Override + protected void onBackground() { + LogUtil.info(TAG, "onBackground is called"); + player.getLifecycle().onBackground(); + super.onBackground(); + } + + @Override + protected void onStop() { + LogUtil.info(TAG, "onStop is called"); + playerLoading.unbind(); + controllerView.unbind(); + super.onStop(); + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/SoundRecordSlice.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/SoundRecordSlice.java new file mode 100644 index 0000000000000000000000000000000000000000..c1362e975ac187f3188c855d46889daa5ffa0931 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/SoundRecordSlice.java @@ -0,0 +1,236 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.slice; + +import com.huawei.harmonyaudiodemo.ResourceTable; +import com.huawei.harmonyaudiodemo.constant.Const; +import com.huawei.harmonyaudiodemo.media.AudioRecorder; +import com.huawei.harmonyaudiodemo.media.AudioRender; +import com.huawei.harmonyaudiodemo.util.LogUtil; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Button; +import ohos.agp.components.Component; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.RoundProgressBar; +import ohos.agp.components.SlideDrawer; +import ohos.agp.components.Switch; +import ohos.agp.components.element.FrameAnimationElement; +import ohos.app.Environment; +import ohos.multimodalinput.event.TouchEvent; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +/** + * SoundRecordSlice + * + * @since 2021-04-04 + */ +public class SoundRecordSlice extends AbilitySlice { + private static final String TAG = SoundRecordSlice.class.getSimpleName(); + private FrameAnimationElement frameAnimationElement; + private RoundProgressBar recordProgressBar; + private Button recordButton; + private SlideDrawer slideDrawer; + private Component playAnimView; + private AudioRecorder audioRecorder; + private AudioRender recordWithPlayRender; + private AudioRender oneOffLoadRender; + private boolean isRealTimePlay; + private String savefilePath; + private int recordTag; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_media_sound_audio); + initAnimation(); + initView(); + initListener(); + initRecorder(); + setupRecordWithPlayRender(); + setupOneOffLoadRender(); + } + + private void initAnimation() { + frameAnimationElement = new FrameAnimationElement(getContext(), ResourceTable.Graphic_animation_record_play); + } + + private void initView() { + if (findComponentById(ResourceTable.Id_real_time_switch) instanceof Switch) { + Switch realTimeSwitch = (Switch) findComponentById(ResourceTable.Id_real_time_switch); + realTimeSwitch.setCheckedStateChangedListener((absButton, bool) -> { + isRealTimePlay = bool; + if (isRealTimePlay) { + slideDrawer.closeSmoothly(); + oneOffLoadRender.stop(); + } + }); + } + initRecordView(); + initPlayView(); + } + + private void initListener() { + recordButton.setTouchEventListener(new Component.TouchEventListener() { + private int progress = 0; + + @Override + public boolean onTouchEvent(Component component, TouchEvent touchEvent) { + if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN + || touchEvent.getAction() == TouchEvent.OTHER_POINT_DOWN) { + progress = 0; + oneOffLoadRender.stop(); + recordWithPlayRender.stop(); + } + int action = progress >= Const.NUMBER_500 ? TouchEvent.CANCEL : touchEvent.getAction(); + recordButton.setPressState(true); + switch (action) { + case TouchEvent.PRIMARY_POINT_UP: + case TouchEvent.OTHER_POINT_UP: + case TouchEvent.CANCEL: + recordButton.setPressState(false); + recordProgressBar.setProgressValue(0); + shutdownRecord(); + return false; + default: + progress++; + beginRecord(); + break; + } + recordProgressBar.setProgressValue(progress); + return true; + } + }); + } + + private void initRecordView() { + if (findComponentById(ResourceTable.Id_progressbar_record) instanceof RoundProgressBar) { + recordProgressBar = (RoundProgressBar) findComponentById(ResourceTable.Id_progressbar_record); + } + if (findComponentById(ResourceTable.Id_button_record) instanceof Button) { + recordButton = (Button) findComponentById(ResourceTable.Id_button_record); + } + recordProgressBar.setMaxValue(Const.NUMBER_500); + } + + private void initPlayView() { + if (findComponentById(ResourceTable.Id_slide_drawer_record) instanceof SlideDrawer) { + slideDrawer = (SlideDrawer) findComponentById(ResourceTable.Id_slide_drawer_record); + } + slideDrawer.setDisplayMode(SlideDrawer.DisplayMode.WITH_ANIMATION); + slideDrawer.setSlideEnabled(false); + slideDrawer.setTouchForClose(false); + Component playButton = LayoutScatter + .getInstance(this) + .parse(ResourceTable.Layout_record_play_button, null, false); + playAnimView = playButton.findComponentById(ResourceTable.Id_animation_view); + playAnimView.setBackground(frameAnimationElement); + SlideDrawer.LayoutConfig layoutConfig = new SlideDrawer + .LayoutConfig(Const.NUMBER_300, Const.NUMBER_114, SlideDrawer.SlideDirection.START); + layoutConfig.setMarginsLeftAndRight(Const.NUMBER_60, 0); + playButton.setLayoutConfig(layoutConfig); + slideDrawer.addComponent(playButton); + playButton.setClickedListener(component -> { + oneOffLoadRender.stop(); + getUITaskDispatcher().asyncDispatch(() -> playAnimView.setVisibility(Component.VISIBLE)); + frameAnimationElement.start(); + playLocalAudioFile(); + }); + } + + private void initRecorder() { + savefilePath = getExternalFilesDir(Environment.DIRECTORY_MUSIC) + File.separator + "AudioTest.mp3"; + audioRecorder = new AudioRecorder.Builder().setSaveFilePath(savefilePath).create(); + } + + private void setupRecordWithPlayRender() { + recordWithPlayRender = new AudioRender.Builder().setOneOffLoad(false).create(); + audioRecorder.setAudioRecordListener((buffer, length) -> { + if (recordTag == 0) { + recordWithPlayRender.play(buffer, length); + } + }); + } + + private void setupOneOffLoadRender() { + oneOffLoadRender = new AudioRender.Builder().create(); + oneOffLoadRender.setPlayListener(() -> { + frameAnimationElement.stop(); + getUITaskDispatcher().asyncDispatch(() -> playAnimView.setVisibility(Component.INVISIBLE)); + }); + } + + private void shutdownRecord() { + if (audioRecorder.isRecording()) { + audioRecorder.stopRecord(); + } + if (!isRealTimePlay) { + slideDrawer.openSmoothly(); + } + } + + private void beginRecord() { + if (!audioRecorder.isRecording()) { + recordTag = isRealTimePlay ? 0 : 1; + audioRecorder.record(); + } + } + + private void playLocalAudioFile() { + BufferedInputStream bis = null; + try { + bis = new BufferedInputStream(new FileInputStream(savefilePath)); + byte[] buffers = new byte[bis.available()]; + int len; + while ((len = bis.read(buffers)) != Const.NUMBER_NEGATIVE_1) { + oneOffLoadRender.play(buffers, len); + } + } catch (IOException e) { + LogUtil.error(TAG, "play local audio file failed"); + } finally { + if (bis != null) { + try { + bis.close(); + } catch (IOException e) { + LogUtil.error(TAG, "play local audio file failed"); + } + } + } + } + + @Override + public void onActive() { + super.onActive(); + } + + @Override + public void onForeground(Intent intent) { + super.onForeground(intent); + } + + @Override + protected void onStop() { + recordWithPlayRender.release(); + oneOffLoadRender.release(); + audioRecorder.stopRecord(); + super.onStop(); + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/SoundSystemSlice.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/SoundSystemSlice.java new file mode 100644 index 0000000000000000000000000000000000000000..543e740995feac77874522e832eb81db3f166da8 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/SoundSystemSlice.java @@ -0,0 +1,116 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.slice; + +import com.huawei.harmonyaudiodemo.ResourceTable; +import com.huawei.harmonyaudiodemo.constant.Const; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.media.audio.SoundPlayer; +import ohos.media.audio.ToneDescriptor; + +/** + * SoundSystemSlice + * + * @since 2021-04-04 + */ +public class SoundSystemSlice extends AbilitySlice implements Component.ClickedListener { + private SoundPlayer soundPlayer; + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_media_sound_tone); + initView(); + initPlayer(); + } + + private void initView() { + findComponentById(ResourceTable.Id_sound0).setClickedListener(this); + findComponentById(ResourceTable.Id_sound1).setClickedListener(this); + findComponentById(ResourceTable.Id_sound2).setClickedListener(this); + findComponentById(ResourceTable.Id_sound3).setClickedListener(this); + findComponentById(ResourceTable.Id_sound4).setClickedListener(this); + findComponentById(ResourceTable.Id_sound5).setClickedListener(this); + findComponentById(ResourceTable.Id_sound6).setClickedListener(this); + findComponentById(ResourceTable.Id_sound7).setClickedListener(this); + findComponentById(ResourceTable.Id_sound8).setClickedListener(this); + findComponentById(ResourceTable.Id_sound9).setClickedListener(this); + } + + private void initPlayer() { + soundPlayer = new SoundPlayer(); + } + + @Override + public void onClick(Component view) { + switch (view.getId()) { + case ResourceTable.Id_sound0: + soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_0, Const.NUMBER_500); + soundPlayer.play(); + break; + case ResourceTable.Id_sound1: + soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_1, Const.NUMBER_500); + soundPlayer.play(); + break; + case ResourceTable.Id_sound2: + soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_2, Const.NUMBER_500); + soundPlayer.play(); + break; + case ResourceTable.Id_sound3: + soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_3, Const.NUMBER_500); + soundPlayer.play(); + break; + case ResourceTable.Id_sound4: + soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_4, Const.NUMBER_500); + soundPlayer.play(); + break; + case ResourceTable.Id_sound5: + soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_5, Const.NUMBER_500); + soundPlayer.play(); + break; + case ResourceTable.Id_sound6: + soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_6, Const.NUMBER_500); + soundPlayer.play(); + break; + case ResourceTable.Id_sound7: + soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_7, Const.NUMBER_500); + soundPlayer.play(); + break; + case ResourceTable.Id_sound8: + soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_8, Const.NUMBER_500); + soundPlayer.play(); + break; + case ResourceTable.Id_sound9: + soundPlayer.createSound(ToneDescriptor.ToneType.DTMF_9, Const.NUMBER_500); + soundPlayer.play(); + break; + default: + break; + } + } + + @Override + protected void onStop() { + if (soundPlayer != null) { + soundPlayer.release(); + soundPlayer = null; + } + super.onStop(); + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/SoundVolumeSlice.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/SoundVolumeSlice.java new file mode 100644 index 0000000000000000000000000000000000000000..8e295f054de7ebe323fc6eaa271932b385070ff4 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/slice/SoundVolumeSlice.java @@ -0,0 +1,140 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.slice; + +import com.huawei.harmonyaudiodemo.ResourceTable; +import com.huawei.harmonyaudiodemo.util.LogUtil; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Slider; +import ohos.agp.components.Slider.ValueChangedListener; +import ohos.media.audio.AudioManager; +import ohos.media.audio.AudioRemoteException; + +/** + * SoundVolumeSlice + * + * @since 2021-04-04 + */ +public class SoundVolumeSlice extends AbilitySlice implements ValueChangedListener { + private static final String TAG = SoundVolumeSlice.class.getName(); + private AudioManager audioManager; + private int dtmfVolume; + private int musicVolume; + private int callVolume; + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_media_sound_volume); + audioManager = new AudioManager(); + initView(); + } + + private void initView() { + try { + initSlider(ResourceTable.Id_sound_volume_bar); + initSlider(ResourceTable.Id_sound_volume_bar2); + initSlider(ResourceTable.Id_sound_volume_bar3); + } catch (AudioRemoteException e) { + LogUtil.error(TAG, "audio remote exception"); + } + } + + private void initSlider(int id) throws AudioRemoteException { + Slider slider = null; + if (findComponentById(id) instanceof Slider) { + slider = (Slider) findComponentById(id); + } + int maxValue = 0; + int currentValue = 0; + switch (id) { + case ResourceTable.Id_sound_volume_bar: + maxValue = audioManager.getMaxVolume(AudioManager.AudioVolumeType.STREAM_DTMF); + currentValue = audioManager.getVolume(AudioManager.AudioVolumeType.STREAM_DTMF); + dtmfVolume = currentValue; + break; + case ResourceTable.Id_sound_volume_bar2: + maxValue = audioManager.getMaxVolume(AudioManager.AudioVolumeType.STREAM_MUSIC); + currentValue = audioManager.getVolume(AudioManager.AudioVolumeType.STREAM_MUSIC); + musicVolume = currentValue; + break; + case ResourceTable.Id_sound_volume_bar3: + maxValue = audioManager.getMaxVolume(AudioManager.AudioVolumeType.STREAM_VOICE_CALL); + currentValue = audioManager.getVolume(AudioManager.AudioVolumeType.STREAM_VOICE_CALL); + callVolume = currentValue; + break; + default: + break; + } + if (slider != null) { + slider.setMaxValue(maxValue); + slider.setProgressValue(currentValue); + slider.setValueChangedListener(this); + } + } + + @Override + public void onProgressUpdated(Slider slider, int info, boolean isBool) { + } + + @Override + public void onTouchStart(Slider slider) { + } + + @Override + public void onTouchEnd(Slider slider) { + int progress = slider.getProgress(); + switch (slider.getId()) { + case ResourceTable.Id_sound_volume_bar: + try { + if (audioManager.setVolume(AudioManager.AudioVolumeType.STREAM_DTMF, progress)) { + dtmfVolume = progress; + } else { + audioManager.setVolume(AudioManager.AudioVolumeType.STREAM_DTMF, dtmfVolume); + } + } catch (SecurityException e) { + LogUtil.error(TAG, "set dtmf volume error"); + } + break; + case ResourceTable.Id_sound_volume_bar2: + try { + if (audioManager.setVolume(AudioManager.AudioVolumeType.STREAM_MUSIC, progress)) { + musicVolume = progress; + } else { + audioManager.setVolume(AudioManager.AudioVolumeType.STREAM_MUSIC, musicVolume); + } + } catch (SecurityException e) { + LogUtil.error(TAG, "set music volume error"); + } + break; + case ResourceTable.Id_sound_volume_bar3: + try { + if (audioManager.setVolume(AudioManager.AudioVolumeType.STREAM_VOICE_CALL, progress)) { + callVolume = progress; + } else { + audioManager.setVolume(AudioManager.AudioVolumeType.STREAM_VOICE_CALL, callVolume); + } + } catch (SecurityException e) { + LogUtil.error(TAG, "set call volume error"); + } + break; + default: + break; + } + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/util/LogUtil.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/util/LogUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..65d08bd0320d62a395b758e83d236470344199a9 --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/util/LogUtil.java @@ -0,0 +1,75 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.util; + +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + +/** + * Log util + * + * @since 2021-04-04 + */ +public class LogUtil { + private static final String TAG_LOG = "LogUtil"; + + private static final HiLogLabel LABEL_LOG = new HiLogLabel(0, 0, LogUtil.TAG_LOG); + + private static final String LOG_FORMAT = "%{public}s: %{public}s"; + + private LogUtil() { + } + + /** + * Print debug log + * + * @param tag log tag + * @param msg log message + */ + public static void debug(String tag, String msg) { + HiLog.debug(LABEL_LOG, LOG_FORMAT, tag, msg); + } + + /** + * Print info log + * + * @param tag log tag + * @param msg log message + */ + public static void info(String tag, String msg) { + HiLog.info(LABEL_LOG, LOG_FORMAT, tag, msg); + } + + /** + * Print warn log + * + * @param tag log tag + * @param msg log message + */ + public static void warn(String tag, String msg) { + HiLog.warn(LABEL_LOG, LOG_FORMAT, tag, msg); + } + + /** + * Print error log + * + * @param tag log tag + * @param msg log message + */ + public static void error(String tag, String msg) { + HiLog.error(LABEL_LOG, LOG_FORMAT, tag, msg); + } +} diff --git a/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/util/ScreenUtils.java b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/util/ScreenUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..f2cc386daad3fdd329dd6094734b9e6e416ba73a --- /dev/null +++ b/AudioDemo/entry/src/main/java/com/huawei/harmonyaudiodemo/util/ScreenUtils.java @@ -0,0 +1,96 @@ +/* + * 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. + */ + +package com.huawei.harmonyaudiodemo.util; + +import ohos.agp.utils.Point; +import ohos.agp.window.service.Display; +import ohos.agp.window.service.DisplayManager; +import ohos.app.Context; +import ohos.global.configuration.DeviceCapability; + +import java.util.Optional; + +/** + * Screen util + * + * @since 2021-04-04 + */ +public class ScreenUtils { + private ScreenUtils() { + } + + /** + * getScreenHeight + * + * @param context context + * @return Screen Height + */ + public static int getScreenHeight(Context context) { + DisplayManager displayManager = DisplayManager.getInstance(); + Optional optDisplay = displayManager.getDefaultDisplay(context); + Point point = new Point(0, 0); + if (!optDisplay.isPresent()) { + return (int) point.position[1]; + } else { + Display display = optDisplay.get(); + display.getSize(point); + return (int) point.position[1]; + } + } + + /** + * getScreenWidth + * + * @param context context + * @return Screen Width + */ + public static int getScreenWidth(Context context) { + DisplayManager displayManager = DisplayManager.getInstance(); + Optional optDisplay = displayManager.getDefaultDisplay(context); + Point point = new Point(0, 0); + if (!optDisplay.isPresent()) { + return (int) point.position[0]; + } else { + Display display = optDisplay.get(); + display.getSize(point); + return (int) point.position[0]; + } + } + + /** + * dp2px + * + * @param context context + * @param size size + * @return int + */ + public static int dp2px(Context context, int size) { + int density = context.getResourceManager().getDeviceCapability().screenDensity / DeviceCapability.SCREEN_MDPI; + return size * density; + } + + /** + * px2dip + * + * @param context context + * @param size size + * @return int + */ + public static int px2dip(Context context, int size) { + int density = context.getResourceManager().getDeviceCapability().screenDensity / DeviceCapability.SCREEN_MDPI; + return size / density; + } +} diff --git a/AudioDemo/entry/src/ohosTest/config.json b/AudioDemo/entry/src/ohosTest/config.json index 20e47eb2717894191bc2b46da933c609cab80366..a7569cd667f81fca7f89579c63286460db087f60 100644 --- a/AudioDemo/entry/src/ohosTest/config.json +++ b/AudioDemo/entry/src/ohosTest/config.json @@ -1,6 +1,6 @@ { "app": { - "bundleName": "com.huawei.harmonyaudiodemo", + "bundleName": "com.huawei.cookbook", "vendor": "huawei", "version": { "code": 1, @@ -8,8 +8,7 @@ }, "apiVersion": { "compatible": 4, - "target": 4, - "releaseType": "Beta1" + "target": 4 } }, "deviceConfig": {}, diff --git a/AudioDemo/gradle/wrapper/gradle-wrapper.properties b/AudioDemo/gradle/wrapper/gradle-wrapper.properties index 6623300bebd011bc5f7991f4f9c389e2f67b14ac..f59159e865d4b59feb1b8c44b001f62fc5d58df4 100644 --- a/AudioDemo/gradle/wrapper/gradle-wrapper.properties +++ b/AudioDemo/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +distributionUrl=https\://repo.huaweicloud.com/gradle/gradle-6.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/ComponentCodelab/LICENSE b/ComponentCodelab/LICENSE index 80576ef141485b36eea4aebf25af97020bc2de44..7c357dc828cf7d8c783f10ed6bb1bac8a1e903c1 100644 --- a/ComponentCodelab/LICENSE +++ b/ComponentCodelab/LICENSE @@ -1,10 +1,10 @@ - Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. + Copyright (c) 2021 Huawei Device Co., Ltd. - Licensed under the Apache License, Version 2.0 (the "License"); + 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 + 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, diff --git a/ComponentCodelab/README.md b/ComponentCodelab/README.md index 2b6de728f6acd0e5fb5201a1d9b6362e31bd1a44..365833ac16ef6e389cab1e3c55b1203438743b2f 100644 --- a/ComponentCodelab/README.md +++ b/ComponentCodelab/README.md @@ -1,13 +1,12 @@ -ComponentCodelab - +# ComponentCodelab 简介 - • 本CodeLab旨在使开发人员了解用于HarmonyOS手机应用程序开发的通用组件的通用布局和使用方法,并体验从项目创建到代码和布局编写,再到编译、构造、部署和运行的全过程。 +• 本CodeLab旨在使开发人员了解用于HarmonyOS手机应用程序开发的通用组件的通用布局和使用方法,并体验从项目创建到代码和布局编写,再到编译、构造、部署和运行的全过程。 安装要求 -• 安装DevEco Studio和Node.js -• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: - 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK - 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 安装DevEco Studio +• 设置DevEco Studio开发环境。DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 • 生成密钥并申请证书 用户指南 @@ -17,9 +16,31 @@ ComponentCodelab • 单击Run> Run 'entry'以运行hap包 注意 -• 项目代码的存储目录需使用英语字符。 -• 您可以选择在模拟器或真机上运行hap软件包。 +• 您可以选择在模拟器或真机上运行hap软件包。 • 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 - + 许可 -请参阅LICENSE文件以获得更多信息。 \ No newline at end of file +请参阅LICENSE文件以获得更多信息。 + +What is it? +This CodeLab aims to let developers understand the common layouts and usage methods of common components for mobile HarmonyOS application development, and experience the whole process from project creation to code and layout writing, to compilation, construction, deployment, and operation. + +Installation requirements +• Install DevEco Studio +• Set up the DevEco Studio development environment.The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool.The development environment can be configured according to the following two situations + 1.If you can directly access the Internet, just download the HarmonyOS SDK + 2.If the network cannot access the Internet directly, it can be accessed through a proxy server +• Generate secret key and apply for certificate + +User guide +• Download this Project +• Open HUAWEI DevEco Studio, click File> Open> Then select and open this Project +• Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package +• Click Run> Run 'entry' to run the hap package + +Note +• You can choose to run the hap package on the simulator or the phone. +• If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. + +Licensing +Please see LICENSE for more info. \ No newline at end of file diff --git a/ComponentCodelab/build.gradle b/ComponentCodelab/build.gradle index 14d3cf79a4c787374f9646244fe5ee1f5bca73d6..0cdb1590ae7440ce7a35f6a3f6d2e970542c718e 100644 --- a/ComponentCodelab/build.gradle +++ b/ComponentCodelab/build.gradle @@ -2,35 +2,36 @@ apply plugin: 'com.huawei.ohos.app' ohos { - compileSdkVersion 4 + compileSdkVersion 5 defaultConfig { - compatibleSdkVersion 3 + compatibleSdkVersion 4 } } - + buildscript { repositories { maven { - url 'https://mirrors.huaweicloud.com/repository/maven/' + url 'https://repo.huaweicloud.com/repository/maven/' } maven { url 'https://developer.huawei.com/repo/' } - jcenter() + jcenter() } dependencies { - classpath 'com.huawei.ohos:hap:2.4.0.1' + classpath 'com.huawei.ohos:hap:2.4.2.7' + classpath 'com.huawei.ohos:decctest:1.0.0.7' } } allprojects { repositories { maven { - url 'https://mirrors.huaweicloud.com/repository/maven/' + url 'https://repo.huaweicloud.com/repository/maven/' } maven { url 'https://developer.huawei.com/repo/' } - jcenter() + jcenter() } -} +} \ No newline at end of file diff --git a/ComponentCodelab/entry/build.gradle b/ComponentCodelab/entry/build.gradle index 78fc120f113c7e94e41bab3a2b2429d98d21b946..95059698209dd4e70219f28daef063de0a9cde67 100644 --- a/ComponentCodelab/entry/build.gradle +++ b/ComponentCodelab/entry/build.gradle @@ -1,12 +1,25 @@ apply plugin: 'com.huawei.ohos.hap' +apply plugin: 'com.huawei.ohos.decctest' ohos { - compileSdkVersion 4 + compileSdkVersion 5 defaultConfig { - compatibleSdkVersion 3 + compatibleSdkVersion 4 + } + buildTypes { + release { + proguardOpt { + proguardEnabled false + rulesFiles 'proguard-rules.pro' + } + } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) - testCompile'junit:junit:4.12' + testImplementation 'junit:junit:4.13' + ohosTestImplementation 'com.huawei.ohos.testkit:runner:1.0.0.100' +} +decc { + supportType = ['html','xml'] } diff --git a/ComponentCodelab/entry/src/main/config.json b/ComponentCodelab/entry/src/main/config.json index be3efd3a6e992b2e4d3f766d1bc1301564560a4f..56635f1969dafbc4d02eb96880267ff9557251b5 100644 --- a/ComponentCodelab/entry/src/main/config.json +++ b/ComponentCodelab/entry/src/main/config.json @@ -7,9 +7,9 @@ "name": "1.0" }, "apiVersion": { - "compatible": 3, - "target": 4, - "releaseType": "Beta1" + "compatible": 4, + "target": 5, + "releaseType": "Release" } }, "deviceConfig": {}, diff --git a/ComponentCodelab/entry/src/main/java/com/huawei/codelab/MainAbility.java b/ComponentCodelab/entry/src/main/java/com/huawei/codelab/MainAbility.java index cf46c918215c8a740123602a24933fa248d271e1..00e0c6abb187ac2831a73560f2ca607014013079 100644 --- a/ComponentCodelab/entry/src/main/java/com/huawei/codelab/MainAbility.java +++ b/ComponentCodelab/entry/src/main/java/com/huawei/codelab/MainAbility.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/ComponentCodelab/entry/src/main/java/com/huawei/codelab/MyApplication.java b/ComponentCodelab/entry/src/main/java/com/huawei/codelab/MyApplication.java index f3afea72b566f491c7eb521569b1c406ea693bf3..b13374ec48666aebed5571afd0054435f7403149 100644 --- a/ComponentCodelab/entry/src/main/java/com/huawei/codelab/MyApplication.java +++ b/ComponentCodelab/entry/src/main/java/com/huawei/codelab/MyApplication.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/ComponentCodelab/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java b/ComponentCodelab/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java index 0955d9e4268f56fc93746f4c968e34cd40046630..d4e8d749e7aca1dea4ce61a33b425d464a9273f2 100644 --- a/ComponentCodelab/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java +++ b/ComponentCodelab/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * @@ -74,7 +73,7 @@ public class MainAbilitySlice extends AbilitySlice implements Component.ClickedL if (object instanceof AbilitySlice) { present((AbilitySlice) object, new Intent()); } - } catch (Exception e) { + } catch (ReflectiveOperationException e) { new ToastDialog(getContext()) .setText("Error!") .show(); diff --git a/ComponentCodelab/gradle/wrapper/gradle-wrapper.properties b/ComponentCodelab/gradle/wrapper/gradle-wrapper.properties index 6623300bebd011bc5f7991f4f9c389e2f67b14ac..bf127d05e72e6d10a23778bd97ee29ac8c849bba 100644 --- a/ComponentCodelab/gradle/wrapper/gradle-wrapper.properties +++ b/ComponentCodelab/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +distributionUrl=https\://repo.huaweicloud.com/gradle/gradle-6.3-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/DistributedMail/LICENSE b/DistributedMail/LICENSE index 80576ef141485b36eea4aebf25af97020bc2de44..7c357dc828cf7d8c783f10ed6bb1bac8a1e903c1 100644 --- a/DistributedMail/LICENSE +++ b/DistributedMail/LICENSE @@ -1,10 +1,10 @@ - Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. + Copyright (c) 2021 Huawei Device Co., Ltd. - Licensed under the Apache License, Version 2.0 (the "License"); + 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 + 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, diff --git a/DistributedMail/README.md b/DistributedMail/README.md index d7fbe336d08e929fece5f6f48bea28cff0068ccb..812a68499ca4c8756308e22b6e61ea8381dbf68f 100644 --- a/DistributedMail/README.md +++ b/DistributedMail/README.md @@ -1,13 +1,12 @@ -# 分布式邮件客户端 - +# DistributedMail 简介 -在本文中,我们模拟演示了跨设备的电子邮件编辑页面。我们可以通过迁移按钮完成跨设备迁移的任务,并通过附件按钮调用跨设备图片。 +• 在本文中,我们模拟演示了跨设备的电子邮件编辑页面。我们可以通过迁移按钮完成跨设备迁移的任务,并通过附件按钮调用跨设备图片。 安装要求 -• 安装DevEco Studio和Node.js -• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: - 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK - 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 安装DevEco Studio +• 设置DevEco Studio开发环境。DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 • 生成密钥并申请证书 用户指南 @@ -17,8 +16,31 @@ • 单击Run> Run 'entry'以运行hap包 注意 -• 您可以选择在模拟器或真机上运行hap软件包。 +• 您可以选择在模拟器或真机上运行hap软件包。 • 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 许可 -请参阅LICENSE文件以获得更多信息。 \ No newline at end of file +请参阅LICENSE文件以获得更多信息。 + +What is it? +In this article, we make a simple demonstration by simulating the collaborative email editing between different devices. We can complete the task of cross device migration through the migration button, and call the cross device pictures through the attachment button. + +Installation requirements +• Install DevEco Studio +• Set up the DevEco Studio development environment.The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool.The development environment can be configured according to the following two situations + 1.If you can directly access the Internet, just download the HarmonyOS SDK + 2.If the network cannot access the Internet directly, it can be accessed through a proxy server +• Generate secret key and apply for certificate + +User guide +• Download this Project +• Open HUAWEI DevEco Studio, click File> Open> Then select and open this Project +• Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package +• Click Run> Run 'entry' to run the hap package + +Note +• You can choose to run the hap package on the simulator or the phone. +• If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. + +Licensing +Please see LICENSE for more info. \ No newline at end of file diff --git a/DistributedMail/build.gradle b/DistributedMail/build.gradle index 9ec29b00390d8a9ea93959252e81018c673268ba..cee07328749cf41637db2e71b7fbf43f6bde41e4 100644 --- a/DistributedMail/build.gradle +++ b/DistributedMail/build.gradle @@ -7,7 +7,7 @@ ohos { compatibleSdkVersion 4 } } - + buildscript { repositories { maven { @@ -16,7 +16,7 @@ buildscript { maven { url 'https://developer.huawei.com/repo/' } - jcenter() + jcenter() } dependencies { classpath 'com.huawei.ohos:hap:2.4.2.7' @@ -32,6 +32,6 @@ allprojects { maven { url 'https://developer.huawei.com/repo/' } - jcenter() + jcenter() } } diff --git a/DistributedMail/entry/build.gradle b/DistributedMail/entry/build.gradle index 58332659cff5989dd026ee2aebef6f77e0f833c8..95059698209dd4e70219f28daef063de0a9cde67 100644 --- a/DistributedMail/entry/build.gradle +++ b/DistributedMail/entry/build.gradle @@ -5,13 +5,21 @@ ohos { defaultConfig { compatibleSdkVersion 4 } + buildTypes { + release { + proguardOpt { + proguardEnabled false + rulesFiles 'proguard-rules.pro' + } + } + } } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - testCompile 'junit:junit:4.13' + implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) + testImplementation 'junit:junit:4.13' ohosTestImplementation 'com.huawei.ohos.testkit:runner:1.0.0.100' } decc { - supportType = ['html', 'xml'] + supportType = ['html','xml'] } diff --git a/DistributedMail/entry/src/main/config.json b/DistributedMail/entry/src/main/config.json index 70f58af9d3cbfd99ac134f0a6c130cbec0c24760..9d49bd38c2bc39d36eb178ec3fcfa1f893f9ea4f 100644 --- a/DistributedMail/entry/src/main/config.json +++ b/DistributedMail/entry/src/main/config.json @@ -8,7 +8,8 @@ }, "apiVersion": { "compatible": 4, - "target": 5 + "target": 5, + "releaseType": "Release" } }, "deviceConfig": {}, diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/MainAbility.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/MainAbility.java index c72cda11f4e0c3f1e0fc124e0585bfaf3c5bf704..84260f406ce5fcbb9509c259700ef4222e0660da 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/MainAbility.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/MainAbility.java @@ -1,10 +1,10 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * 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, @@ -50,17 +50,21 @@ public class MainAbility extends Ability implements IAbilityContinuation { List applyPermissions = new ArrayList<>(); for (String element : permissions) { LogUtil.info(TAG, "check permission: " + element); - if (verifySelfPermission(element) != 0) { - if (canRequestPermission(element)) { - applyPermissions.add(element); - } else { - LogUtil.info(TAG, "user deny permission"); - } + checkPermission(applyPermissions, element); + } + requestPermissionsFromUser(applyPermissions.toArray(new String[0]), 0); + } + + private void checkPermission(List applyPermissions, String element) { + if (verifySelfPermission(element) != 0) { + if (canRequestPermission(element)) { + applyPermissions.add(element); } else { - LogUtil.info(TAG, "user granted permission: " + element); + LogUtil.info(TAG, "user deny permission"); } + } else { + LogUtil.info(TAG, "user granted permission: " + element); } - requestPermissionsFromUser(applyPermissions.toArray(new String[0]), 0); } @Override diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/MyApplication.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/MyApplication.java index fcdcc39bad3d2bb43014013e621d2de6ef743947..83857adf2eacf810a14e7818205677c4d9189caa 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/MyApplication.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/MyApplication.java @@ -1,10 +1,10 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * 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, diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/bean/MailDataBean.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/bean/MailDataBean.java index b61a3cff8a3ea1e7841b73128dd0a431c58180a3..92468df59ec29719b52e0138476aebdd3dd14db4 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/bean/MailDataBean.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/bean/MailDataBean.java @@ -1,10 +1,10 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * 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, diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/data/DeviceData.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/data/DeviceData.java index be9730a2c1951d69e154eaefbf0660ad12cc466e..cba8ed9988f4cb1bac5e1c201b9a58bd4c3676aa 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/data/DeviceData.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/data/DeviceData.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/slice/MailEditSlice.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/slice/MailEditSlice.java index 9b1318a8732697f68d8c60b6f58e5368c6bb6840..ee9bf0d372f6de49215995821b30df0a5bd0096f 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/slice/MailEditSlice.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/slice/MailEditSlice.java @@ -1,10 +1,10 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * 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, @@ -125,7 +125,7 @@ public class MailEditSlice extends AbilitySlice implements IAbilityContinuation fillView(); setAttachmentProvider(rootView); - rootView.findComponentById(ResourceTable.Id_call_test).setClickedListener(c -> { }); + rootView.findComponentById(ResourceTable.Id_call_test).setClickedListener(listener -> { }); } private void setAttachmentProvider(Component rootView) { @@ -147,6 +147,12 @@ public class MailEditSlice extends AbilitySlice implements IAbilityContinuation .setPixelMap(source.createPixelmap(0, null)); } catch (FileNotFoundException e) { LogUtil.error(TAG, "setAttachmentProvider Error"); + } finally { + try { + fileInputStream.close(); + } catch (IOException e) { + LogUtil.error(TAG, "close fileInputStream Error"); + } } } }; @@ -244,6 +250,12 @@ public class MailEditSlice extends AbilitySlice implements IAbilityContinuation .setPixelMap(source.createPixelmap(0, null)); } catch (FileNotFoundException e) { LogUtil.error(TAG, "showDialog() FileNotFound Exception"); + } finally { + try { + fileInputStream.close(); + } catch (IOException e) { + LogUtil.error(TAG, "close fileInputStream error"); + } } } }; @@ -306,11 +318,11 @@ public class MailEditSlice extends AbilitySlice implements IAbilityContinuation File fr = new File(distributedFilePath); in = new FileInputStream(fileDescriptor); out = new FileOutputStream(fr); - byte[] buffer = new byte[CACHE_SIZE]; + byte[] buffers = new byte[CACHE_SIZE]; int count = 0; LogUtil.info(TAG, "START WRITING"); - while ((count = in.read(buffer)) != IO_END_LEN) { - out.write(buffer, 0, count); + while ((count = in.read(buffers)) != IO_END_LEN) { + out.write(buffers, 0, count); } out.close(); LogUtil.info(TAG, "STOP WRITING"); diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/DeviceSelectDialog.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/DeviceSelectDialog.java index d06cee452734693046d9307d29bfaad108ba0bfc..97dc8c35fb7365808be4add878157872d5cc0f5c 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/DeviceSelectDialog.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/DeviceSelectDialog.java @@ -1,10 +1,10 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * 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, diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/WidgetHelper.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/WidgetHelper.java index 35465e135b5ffaef8ff8d4192a7873dd8e3c0af3..588a7f26b3f3edfff770c2bb3dace86a7843ad13 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/WidgetHelper.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/WidgetHelper.java @@ -1,10 +1,10 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * 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, @@ -126,7 +126,7 @@ public final class WidgetHelper { * Get string value * * @param context ability or ability slice - * @param id resource id + * @param id resource id * @return string value */ public static String getString(Context context, int id) { diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/listcomponent/CommentViewHolder.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/listcomponent/CommentViewHolder.java index ac52539c336af47b9bc5fdbeacf71bf4766f4052..eebdf1455ab56911d48e7c072165cb478cadc5f3 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/listcomponent/CommentViewHolder.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/listcomponent/CommentViewHolder.java @@ -1,10 +1,10 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * 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, @@ -76,6 +76,7 @@ public class CommentViewHolder { * * @param resId resId * @param type type + * @param generics * @return T */ public T getView(int resId, Class type) { diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/listcomponent/ListComponentAdapter.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/listcomponent/ListComponentAdapter.java index c08668ef1bad9aaf40930fdd4c6388522aa3ef85..6b137956eada523ad14591e74d33f1e88e5832dc 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/listcomponent/ListComponentAdapter.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/ui/listcomponent/ListComponentAdapter.java @@ -1,10 +1,10 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * 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, @@ -26,12 +26,13 @@ import java.util.List; /** * ListComponentAdapter * + * @param generics * @since 2021-02-13 */ public abstract class ListComponentAdapter extends BaseItemProvider { LayoutScatter layoutScatter; private Context mContext; - private List mListBean; + private List mListBeans; private int mXmlId; /** @@ -43,7 +44,7 @@ public abstract class ListComponentAdapter extends BaseItemProvider { */ public ListComponentAdapter(Context context, List list, int xmlId) { this.mContext = context; - this.mListBean = list; + this.mListBeans = list; this.mXmlId = xmlId; layoutScatter = LayoutScatter.getInstance(mContext); } @@ -59,12 +60,12 @@ public abstract class ListComponentAdapter extends BaseItemProvider { @Override public int getCount() { - return mListBean.size(); + return mListBeans.size(); } @Override public T getItem(int i) { - return mListBean.get(i); + return mListBeans.get(i); } @Override @@ -75,7 +76,7 @@ public abstract class ListComponentAdapter extends BaseItemProvider { @Override public Component getComponent(int i, Component component, ComponentContainer componentContainer) { CommentViewHolder commentViewHolder = CommentViewHolder.getCommentViewHolder(mContext, component, mXmlId); - T t = mListBean.get(i); + T t = mListBeans.get(i); onBindViewHolder(commentViewHolder, t, i); commentViewHolder.getConvertView().setClickedListener(component1 -> onItemClick(component, t, i)); return commentViewHolder.getConvertView(); diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/utils/DeviceUtils.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/utils/DeviceUtils.java index 8c9c62f8d2c4356c2128c2866c81d2dfad4664c6..13400f6a08029adb748aa226ab80420a31fa30db 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/utils/DeviceUtils.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/utils/DeviceUtils.java @@ -1,10 +1,10 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * 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, @@ -51,11 +51,11 @@ public class DeviceUtils { // 空目录 return new ArrayList<>(); } - List list = new ArrayList<>(); + List lists = new ArrayList<>(); for (File eachFile : files) { - list.add(eachFile.getPath()); + lists.add(eachFile.getPath()); } - return list; + return lists; } } diff --git a/DistributedMail/entry/src/main/java/com/huawei/maildemo/utils/LogUtil.java b/DistributedMail/entry/src/main/java/com/huawei/maildemo/utils/LogUtil.java index 9a621d5adcefbc85e5e671682c312b04c5bcb493..f6b18109042f3573eb0e588785a0a6c9c6fd3bdd 100644 --- a/DistributedMail/entry/src/main/java/com/huawei/maildemo/utils/LogUtil.java +++ b/DistributedMail/entry/src/main/java/com/huawei/maildemo/utils/LogUtil.java @@ -1,10 +1,10 @@ /* * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 + * 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, diff --git a/DistributedMail/gradle/wrapper/gradle-wrapper.properties b/DistributedMail/gradle/wrapper/gradle-wrapper.properties index 6623300bebd011bc5f7991f4f9c389e2f67b14ac..bf127d05e72e6d10a23778bd97ee29ac8c849bba 100644 --- a/DistributedMail/gradle/wrapper/gradle-wrapper.properties +++ b/DistributedMail/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +distributionUrl=https\://repo.huaweicloud.com/gradle/gradle-6.3-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/DistributedMapDemo/LICENSE b/DistributedMapDemo/LICENSE index eb44b24a0ff113ed4b008408a3406f792bde2adb..386f8b9374099acb177755d48a47adbe1ab99f4f 100644 --- a/DistributedMapDemo/LICENSE +++ b/DistributedMapDemo/LICENSE @@ -1,17 +1,38 @@ - Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. + 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. + + We use Google's open-source Gson.jar. The details are as follows: + + ### License + + Gson is released under the [Apache 2.0 license](LICENSE). + + Copyright 2008 Google Inc. 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 + 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 diff --git a/DistributedMapDemo/README.md b/DistributedMapDemo/README.md index 2c4239a087ee7fb685f11650138a2bb721497de8..de47143df49c0d38588306d37a483109a3f3b68f 100644 --- a/DistributedMapDemo/README.md +++ b/DistributedMapDemo/README.md @@ -1,24 +1,46 @@ -DistributedMapDemo - -What is it? The DistributedMapDemo application is to show the simple HarmonyOS Distributed capability. You can simulate navigation through the app. This sample code has been completed for the flow of navigation data between your phone, smart wearable, and tablet. You can work with us from the beginning. This example code is complete and you can learn from the beginning with us. - -Installation requirements • Install DevEco Studio and Node.js • Set up the DevEco Studio development environment. The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool. The development environment can be configured according to the following two situations - -If you can directly access the Internet, just download the HarmonyOS SDK -If the network cannot access the Internet directly, it can be accessed through a proxy server • Generate secret key and apply for certificate -User guide • Download this Project • Open DevEco Studio, click File> Open> Then select and open this Project • Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package • Click Run> Run 'entry' to run the hap package - -Note • You can choose to run the hap package on the simulator or the phone. • If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. - -Licensing Please see LICENSE for more info. - - -简介 • 本篇Codelab旨在展示简单的HarmonyOS分布式功能。您可以通过应用程序模拟导航,在手机、智能穿戴和平板电脑之间进行导航数据流转。 - -安装要求 • 安装DevEco Studio • 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 • 生成密钥并申请证书 - -用户指南 • 下载此项目 • 打开HUAWEI DevEco Studio,单击File> Open选择此DistributedMapDemo • 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 • 单击Run> Run 'entry'以运行hap包 - -注意 • 您可以选择在模拟器或真机上运行hap软件包。 • 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 - -许可 请参阅LICENSE文件以获得更多信息。 \ No newline at end of file +# DistributedMapDemo +简介 +分布式地图应用展示了简单的HarmonyOS分布式能力。您可以通过该应用程序模拟导航。此示例代码完成了手机、智能手表和平板电脑之间的导航数据流转。您和我们从头开始合作。此示例代码已完成,您可以与我们一起从零开始学习。 + +安装要求 +• 安装DevEco Studio +• 设置DevEco Studio开发环境。DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 生成密钥并申请证书 + +用户指南 +• 下载此项目 +• 打开HUAWEI DevEco Studio,单击File> Open选择此ComponentCodelab +• 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 +• 单击Run> Run 'entry'以运行hap包 + +注意 +• 您可以选择在模拟器或真机上运行hap软件包。 +• 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 + +许可 +请参阅LICENSE文件以获得更多信息。 + +What is it? +The DistributedMapDemo application is to show the simple HarmonyOS Distributed capability. You can simulate navigation through the app. This sample code has been completed for the flow of navigation data between your phone, smartwatch, and tablet. You can work with us from the beginning. This example code is complete and you can learn from the beginning with us. + +Installation requirements +• Install DevEco Studio +• Set up the DevEco Studio development environment.The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool.The development environment can be configured according to the following two situations + 1.If you can directly access the Internet, just download the HarmonyOS SDK + 2.If the network cannot access the Internet directly, it can be accessed through a proxy server +• Generate secret key and apply for certificate + +User guide +• Download this Project +• Open HUAWEI DevEco Studio, click File> Open> Then select and open this Project +• Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package +• Click Run> Run 'entry' to run the hap package + +Note +• You can choose to run the hap package on the simulator or the phone. +• If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. + +Licensing +Please see LICENSE for more info. diff --git a/DistributedMapDemo/entry/src/main/idl/com/huawei/codelab/IMapIdlInterface.idl b/DistributedMapDemo/entry/src/main/idl/com/huawei/codelab/IMapIdlInterface.idl index e05490a838afef967df2d4db7bfcf15594cec21f..fc15cf442fac6b4b269586dd3220e9d2388a9c96 100644 --- a/DistributedMapDemo/entry/src/main/idl/com/huawei/codelab/IMapIdlInterface.idl +++ b/DistributedMapDemo/entry/src/main/idl/com/huawei/codelab/IMapIdlInterface.idl @@ -1,6 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * + * 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 diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MainAbility.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MainAbility.java index 66a68ab53e4e4bdc0d8d96c9706fd2964643514b..5479471642ff551fe67878f322ca2ede8ab62ac5 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MainAbility.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MainAbility.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MyApplication.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MyApplication.java index dd9057697ee2324b9a696b15391cc5478571b537..77c37fb449d12ec8d980e95ab82a48a400ec6d78 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MyApplication.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/MyApplication.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchAbility.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchAbility.java index 9831ac017976f6a8f4278902b5bd915a118a4803..2c225edb1555c189f70c8d56fdb793706fd02b22 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchAbility.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchAbility.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchService.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchService.java index d2232e3f3288ad2176b7e11547cced7237eb0f32..06bd296a2837a6eb7bfee988fd9ff722e3b183ad 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchService.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/WatchService.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * @@ -56,6 +55,7 @@ public class WatchService extends Ability { @Override public void onCommand(Intent intent, boolean isRestart, int startId) { + LogUtils.info(TAG, "WatchService::onCommand"); } @Override @@ -65,6 +65,7 @@ public class WatchService extends Ability { @Override public void onDisconnect(Intent intent) { + LogUtils.info(TAG, "WatchService::onDisconnect"); } /** diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/InputTipsResult.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/InputTipsResult.java index f0410a333058ae1cc10328844a7f7b915ed31623..4d16d2e2a0701a6bd373e1012cc297d6efcef015 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/InputTipsResult.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/InputTipsResult.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * @@ -34,101 +33,63 @@ public class InputTipsResult { private String info; - public void setCount(String count) { - this.count = count; - } - - public void setInfocode(String infocode) { - this.infocode = infocode; - } - - public void setTips(List tips) { - this.tips = tips; - } - - public void setStatus(String status) { - this.status = status; - } - - public void setInfo(String info) { - this.info = info; - } - public String getCount() { return count; } + public void setCount(String count) { + this.count = count; + } + public String getInfocode() { return infocode; } + public void setInfocode(String infocode) { + this.infocode = infocode; + } + public List getTips() { return tips; } + public void setTips(List tips) { + this.tips = tips; + } + public String getStatus() { return status; } + public void setStatus(String status) { + this.status = status; + } + public String getInfo() { return info; } + public void setInfo(String info) { + this.info = info; + } + /** * TipsEntity * * @param type * @since 2021-03-12 */ - public class TipsEntity { + public static class TipsEntity { private String typecode; private E address; private E adcode; - private List city; - - private E district; - private String name; private String location; - private E id; - - public void setTypecode(String typecode) { - this.typecode = typecode; - } - - public void setAddress(E address) { - this.address = address; - } - - public void setAdcode(E adcode) { - this.adcode = adcode; - } - - public void setCity(List city) { - this.city = city; - } - - public void setDistrict(E district) { - this.district = district; - } - - public void setName(String name) { - this.name = name; - } - - public void setLocation(String location) { - this.location = location; - } - - public void setId(E id) { - this.id = id; - } - public String getTypecode() { return typecode; } @@ -141,14 +102,6 @@ public class InputTipsResult { return adcode; } - public List getCity() { - return city; - } - - public E getDistrict() { - return district; - } - public String getName() { return name; } @@ -156,9 +109,5 @@ public class InputTipsResult { public String getLocation() { return location; } - - public E getId() { - return id; - } } } diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RegionDetailResult.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RegionDetailResult.java index 8d90d82939743f95c3ebbed1ef6fbcd0876a6988..79763605754c65e991141813f50021b83bc47cf0 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RegionDetailResult.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RegionDetailResult.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * @@ -32,38 +31,38 @@ public class RegionDetailResult { private String info; - public void setInfocode(String infocode) { - this.infocode = infocode; - } - - public void setRegeocode(RegeocodeEntity regeocode) { - this.regeocode = regeocode; - } - - public void setStatus(String status) { - this.status = status; - } - - public void setInfo(String info) { - this.info = info; - } - public String getInfocode() { return infocode; } + public void setInfocode(String infocode) { + this.infocode = infocode; + } + public RegeocodeEntity getRegeocode() { return regeocode; } + public void setRegeocode(RegeocodeEntity regeocode) { + this.regeocode = regeocode; + } + public String getStatus() { return status; } + public void setStatus(String status) { + this.status = status; + } + public String getInfo() { return info; } + public void setInfo(String info) { + this.info = info; + } + /** * RegeocodeEntity * @@ -74,22 +73,22 @@ public class RegionDetailResult { private AddressComponentEntity addressComponent; - public void setFormattedAddress(String formattedAddress) { - this.formattedAddress = formattedAddress; - } - - public void setAddressComponent(AddressComponentEntity addressComponent) { - this.addressComponent = addressComponent; - } - public String getFormattedAddress() { return formattedAddress; } + public void setFormattedAddress(String formattedAddress) { + this.formattedAddress = formattedAddress; + } + public AddressComponentEntity getAddressComponent() { return addressComponent; } + public void setAddressComponent(AddressComponentEntity addressComponent) { + this.addressComponent = addressComponent; + } + /** * AddressComponentEntity * @@ -120,102 +119,102 @@ public class RegionDetailResult { private BuildingEntity building; - public void setBusinessAreas(List> businessAreas) { - this.businessAreas = businessAreas; - } - - public void setCountry(String country) { - this.country = country; - } - - public void setProvince(String province) { - this.province = province; - } - - public void setCitycode(String citycode) { - this.citycode = citycode; - } - - public void setCity(String city) { - this.city = city; - } - - public void setAdcode(String adcode) { - this.adcode = adcode; - } - - public void setStreetNumber(StreetNumberEntity streetNumber) { - this.streetNumber = streetNumber; - } - - public void setTowncode(String towncode) { - this.towncode = towncode; - } - - public void setDistrict(String district) { - this.district = district; - } - - public void setNeighborhood(BuildingEntity neighborhood) { - this.neighborhood = neighborhood; - } - - public void setTownship(String township) { - this.township = township; - } - - public void setBuilding(BuildingEntity building) { - this.building = building; - } - public List> getBusinessAreas() { return businessAreas; } + public void setBusinessAreas(List> businessAreas) { + this.businessAreas = businessAreas; + } + public String getCountry() { return country; } + public void setCountry(String country) { + this.country = country; + } + public String getProvince() { return province; } + public void setProvince(String province) { + this.province = province; + } + public String getCitycode() { return citycode; } + public void setCitycode(String citycode) { + this.citycode = citycode; + } + public String getCity() { return city; } + public void setCity(String city) { + this.city = city; + } + public String getAdcode() { return adcode; } + public void setAdcode(String adcode) { + this.adcode = adcode; + } + public StreetNumberEntity getStreetNumber() { return streetNumber; } + public void setStreetNumber(StreetNumberEntity streetNumber) { + this.streetNumber = streetNumber; + } + public String getTowncode() { return towncode; } + public void setTowncode(String towncode) { + this.towncode = towncode; + } + public String getDistrict() { return district; } + public void setDistrict(String district) { + this.district = district; + } + public BuildingEntity getNeighborhood() { return neighborhood; } + public void setNeighborhood(BuildingEntity neighborhood) { + this.neighborhood = neighborhood; + } + public String getTownship() { return township; } + public void setTownship(String township) { + this.township = township; + } + public BuildingEntity getBuilding() { return building; } + public void setBuilding(BuildingEntity building) { + this.building = building; + } + /** * StreetNumberEntity * @@ -232,45 +231,45 @@ public class RegionDetailResult { private String direction; - public void setNumber(String number) { - this.number = number; - } - - public void setDistance(String distance) { - this.distance = distance; - } - - public void setStreet(String street) { - this.street = street; - } - - public void setLocation(String location) { - this.location = location; - } - - public void setDirection(String direction) { - this.direction = direction; - } - public String getNumber() { return number; } + public void setNumber(String number) { + this.number = number; + } + public String getDistance() { return distance; } + public void setDistance(String distance) { + this.distance = distance; + } + public String getStreet() { return street; } + public void setStreet(String street) { + this.street = street; + } + public String getLocation() { return location; } + public void setLocation(String location) { + this.location = location; + } + public String getDirection() { return direction; } + + public void setDirection(String direction) { + this.direction = direction; + } } /** @@ -283,21 +282,21 @@ public class RegionDetailResult { private List type; - public void setName(List name) { - this.name = name; - } - - public void setType(List type) { - this.type = type; - } - public List getName() { return name; } + public void setName(List name) { + this.name = name; + } + public List getType() { return type; } + + public void setType(List type) { + this.type = type; + } } } } diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RouteResult.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RouteResult.java index 645c9ec3f93f41c20800c304a422f1b57f3b893c..2c0db5fa57b68e8f1109cbd2d5bfda617bf6423e 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RouteResult.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/bean/RouteResult.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * @@ -34,46 +33,46 @@ public class RouteResult { private String info; - public void setRoute(RouteEntity route) { - this.route = route; - } - - public void setCount(String count) { - this.count = count; - } - - public void setInfocode(String infocode) { - this.infocode = infocode; - } - - public void setStatus(String status) { - this.status = status; - } - - public void setInfo(String info) { - this.info = info; - } - public RouteEntity getRoute() { return route; } + public void setRoute(RouteEntity route) { + this.route = route; + } + public String getCount() { return count; } + public void setCount(String count) { + this.count = count; + } + public String getInfocode() { return infocode; } + public void setInfocode(String infocode) { + this.infocode = infocode; + } + public String getStatus() { return status; } + public void setStatus(String status) { + this.status = status; + } + public String getInfo() { return info; } + public void setInfo(String info) { + this.info = info; + } + /** * RouteEntity * @@ -88,38 +87,38 @@ public class RouteResult { private String taxiCost; - public void setPaths(List paths) { - this.paths = paths; - } - - public void setOrigin(String origin) { - this.origin = origin; - } - - public void setDestination(String destination) { - this.destination = destination; - } - - public void setTaxiCost(String taxiCost) { - this.taxiCost = taxiCost; - } - public List getPaths() { return paths; } + public void setPaths(List paths) { + this.paths = paths; + } + public String getOrigin() { return origin; } + public void setOrigin(String origin) { + this.origin = origin; + } + public String getDestination() { return destination; } + public void setDestination(String destination) { + this.destination = destination; + } + public String getTaxiCost() { return taxiCost; } + public void setTaxiCost(String taxiCost) { + this.taxiCost = taxiCost; + } + /** * PathsEntity * @@ -142,70 +141,70 @@ public class RouteResult { private String tolls; - public void setDuration(String duration) { - this.duration = duration; - } - - public void setDistance(String distance) { - this.distance = distance; - } - - public void setRestriction(String restriction) { - this.restriction = restriction; - } - - public void setTollDistance(String tollDistance) { - this.tollDistance = tollDistance; - } - - public void setStrategy(String strategy) { - this.strategy = strategy; - } - - public void setTrafficLights(String trafficLights) { - this.trafficLights = trafficLights; - } - - public void setSteps(List steps) { - this.steps = steps; - } - - public void setTolls(String tolls) { - this.tolls = tolls; - } - public String getDuration() { return duration; } + public void setDuration(String duration) { + this.duration = duration; + } + public String getDistance() { return distance; } + public void setDistance(String distance) { + this.distance = distance; + } + public String getRestriction() { return restriction; } + public void setRestriction(String restriction) { + this.restriction = restriction; + } + public String getTollDistance() { return tollDistance; } + public void setTollDistance(String tollDistance) { + this.tollDistance = tollDistance; + } + public String getStrategy() { return strategy; } + public void setStrategy(String strategy) { + this.strategy = strategy; + } + public String getTrafficLights() { return trafficLights; } + public void setTrafficLights(String trafficLights) { + this.trafficLights = trafficLights; + } + public List getSteps() { return steps; } + public void setSteps(List steps) { + this.steps = steps; + } + public String getTolls() { return tolls; } + public void setTolls(String tolls) { + this.tolls = tolls; + } + /** * StepsEntity * @@ -239,110 +238,110 @@ public class RouteResult { private List tmcs; - public void setOrientation(String orientation) { - this.orientation = orientation; - } - - public void setDistance(String distance) { - this.distance = distance; - } - - public void setCities(List cities) { - this.cities = cities; - } - - public void setTollRoad(E tollRoad) { - this.tollRoad = tollRoad; - } - - public void setTollDistance(String tollDistance) { - this.tollDistance = tollDistance; - } - - public void setTolls(String tolls) { - this.tolls = tolls; - } - - public void setDuration(String duration) { - this.duration = duration; - } - - public void setAssistantAction(E assistantAction) { - this.assistantAction = assistantAction; - } - - public void setRoad(String road) { - this.road = road; - } - - public void setInstruction(String instruction) { - this.instruction = instruction; - } - - public void setAction(E action) { - this.action = action; - } - - public void setPolyline(String polyline) { - this.polyline = polyline; - } - - public void setTmcs(List tmcs) { - this.tmcs = tmcs; - } - public String getOrientation() { return orientation; } + public void setOrientation(String orientation) { + this.orientation = orientation; + } + public String getDistance() { return distance; } + public void setDistance(String distance) { + this.distance = distance; + } + public List getCities() { return cities; } + public void setCities(List cities) { + this.cities = cities; + } + public E getTollRoad() { return tollRoad; } + public void setTollRoad(E tollRoad) { + this.tollRoad = tollRoad; + } + public String getTollDistance() { return tollDistance; } + public void setTollDistance(String tollDistance) { + this.tollDistance = tollDistance; + } + public String getTolls() { return tolls; } + public void setTolls(String tolls) { + this.tolls = tolls; + } + public String getDuration() { return duration; } + public void setDuration(String duration) { + this.duration = duration; + } + public E getAssistantAction() { return assistantAction; } + public void setAssistantAction(E assistantAction) { + this.assistantAction = assistantAction; + } + public String getRoad() { return road; } + public void setRoad(String road) { + this.road = road; + } + public String getInstruction() { return instruction; } + public void setInstruction(String instruction) { + this.instruction = instruction; + } + public E getAction() { return action; } + public void setAction(E action) { + this.action = action; + } + public String getPolyline() { return polyline; } + public void setPolyline(String polyline) { + this.polyline = polyline; + } + public List getTmcs() { return tmcs; } + public void setTmcs(List tmcs) { + this.tmcs = tmcs; + } + /** * CitiesEntity * @@ -357,38 +356,38 @@ public class RouteResult { private List districts; - public void setCitycode(String citycode) { - this.citycode = citycode; - } - - public void setAdcode(String adcode) { - this.adcode = adcode; - } - - public void setName(String name) { - this.name = name; - } - - public void setDistricts(List districts) { - this.districts = districts; - } - public String getCitycode() { return citycode; } + public void setCitycode(String citycode) { + this.citycode = citycode; + } + public String getAdcode() { return adcode; } + public void setAdcode(String adcode) { + this.adcode = adcode; + } + public String getName() { return name; } + public void setName(String name) { + this.name = name; + } + public List getDistricts() { return districts; } + public void setDistricts(List districts) { + this.districts = districts; + } + /** * DistrictsEntity * @@ -399,21 +398,21 @@ public class RouteResult { private String name; - public void setAdcode(String adcode) { - this.adcode = adcode; - } - - public void setName(String name) { - this.name = name; - } - public String getAdcode() { return adcode; } + public void setAdcode(String adcode) { + this.adcode = adcode; + } + public String getName() { return name; } + + public void setName(String name) { + this.name = name; + } } } @@ -431,37 +430,37 @@ public class RouteResult { private String status; - public void setDistance(String distance) { - this.distance = distance; - } - - public void setLcode(E lcode) { - this.lcode = lcode; - } - - public void setPolyline(String polyline) { - this.polyline = polyline; - } - - public void setStatus(String status) { - this.status = status; - } - public String getDistance() { return distance; } + public void setDistance(String distance) { + this.distance = distance; + } + public E getLcode() { return lcode; } + public void setLcode(E lcode) { + this.lcode = lcode; + } + public String getPolyline() { return polyline; } + public void setPolyline(String polyline) { + this.polyline = polyline; + } + public String getStatus() { return status; } + + public void setStatus(String status) { + this.status = status; + } } } } diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/Const.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/Const.java index 4b345fc81d7c3be157e46f509f97c77d09a4425e..f32fa2fa097e35ead649f1a31c7c64562b091d1f 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/Const.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/Const.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * @@ -25,7 +24,7 @@ public class Const { /** * 接口的调用凭证,需要开发者自己申请 */ - public static final String MAP_KAY = ""; + public static final String MAP_KEY = "fdec31f36248c7aa50dd2d252cc773e2"; /** * 高德地图导航瓦片url diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/LocationHelper.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/LocationHelper.java index e3ae8541aa90e6c28bc27ad824486bc2f9c492a9..e0444493e2a74451586f1826dfc29e0283616dae 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/LocationHelper.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/LocationHelper.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapDataHelper.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapDataHelper.java index 481f563ac4eba70a7e0db21cc9e08a10ad6163f6..5f5ce9afc28e3806937a6eb581ae269376a49710 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapDataHelper.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapDataHelper.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * @@ -90,7 +89,7 @@ public class MapDataHelper { * 调用高德地图逆地理编码api,获取城市编码 */ private void getRegionDetail() { - String url = String.format(Const.REGION_DETAIL_URL, location, Const.MAP_KAY); + String url = String.format(Const.REGION_DETAIL_URL, location, Const.MAP_KEY); HttpUtils.getInstance(context).get(url, result -> { RegionDetailResult regionDetailResult = GsonUtils.jsonToBean(result, RegionDetailResult.class); localCityCode = regionDetailResult.getRegeocode().getAddressComponent().getCitycode(); @@ -103,7 +102,7 @@ public class MapDataHelper { * @param keyWords input content */ public void getInputTips(String keyWords) { - String url = String.format(Const.INPUT_TIPS_URL, keyWords, Const.MAP_KAY, location, localCityCode); + String url = String.format(Const.INPUT_TIPS_URL, keyWords, Const.MAP_KEY, location, localCityCode); HttpUtils.getInstance(context).get(url, result -> { InputTipsResult inputTipsResult = GsonUtils.jsonToBean(result, InputTipsResult.class); if (inputTipsResult == null) { @@ -120,7 +119,7 @@ public class MapDataHelper { * @param endLocation 终点路径 */ public void getRouteResult(String endLocation) { - String url = String.format(Const.ROUTE_URL, location, endLocation, Const.MAP_KAY); + String url = String.format(Const.ROUTE_URL, location, endLocation, Const.MAP_KEY); HttpUtils.getInstance(context).get(url, result -> dataCallBack.setRouteView(result)); } diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapElement.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapElement.java index 0f75c67feee9c726f7c9954d6e4fa7ad7737ab3e..2884d2d39b83fd4f635183f93d934d75b17237e4 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapElement.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapElement.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapManager.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapManager.java index 33ecfffb0644ff94df4b1bfa585b03e10739dafd..d55226c9be0504250c283ddb28326aa5725aba29 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapManager.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapManager.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * @@ -89,14 +88,21 @@ public class MapManager { private Runnable task = new Runnable() { @Override public void run() { + // 将定位图标的下一个坐标点的坐标,赋值给当前定位图标 MapElement peopleElement = navMap.getMapElements().get(0); nextElement = navMap.getMapElements().get(stepPoint + 1); peopleElement.setMercatorPoint(nextElement.getMercatorPoint()); peopleElement.setNowPoint(nextElement.getNowPoint()); peopleElement.setOriginPoint(nextElement.getOriginPoint()); + + // 调用sendEvent方法,发送更新UI事件消息 mapEventHandler.sendEvent(1, EventHandler.Priority.IMMEDIATE); + + // 再次调用postTask发送延时任务,让任务持续进行,从而实现坐标的持续移动 mapEventHandler.postTask(task, STEP_DELAY_TIME, EventHandler.Priority.IMMEDIATE); stepPoint++; + + // 将stepPoint传递给NavMap,绘制已经过的路径时也会用到stepPoint navMap.setStepPoint(stepPoint); LogUtils.info(TAG, "run......" + stepPoint); if (stepPoint >= navMap.getMapElements().size() - 1) { diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapTile.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapTile.java index 53dff9c46ef46f2d9840788fa79411420b56ce57..bebc953815d22d675e1a7334948032d6f7d4c1f4 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapTile.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/MapTile.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/NavMap.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/NavMap.java index 52f0b5e77c186013efc46025d36fc55e6b4ab5ce..5647bcf2b34feecc0b2a12fb1edfb20aefa7ee7c 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/NavMap.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/map/NavMap.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/provider/InputTipsProvider.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/provider/InputTipsProvider.java index ec2c4099767cbfe93967053a2c8aaf7f3dc7d454..81b117529d2341b7c77f4547651988fe80a3db3a 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/provider/InputTipsProvider.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/provider/InputTipsProvider.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java index ad634d3a5986069ba1c96a0fa610d995f065bcf7..3efa12c799eaa62abdc45d4c40c8c0f423d7f02d 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/MainAbilitySlice.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/WatchAbilitySlice.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/WatchAbilitySlice.java index 602317af419dbb7df90a31e6ae162280f27f5dd6..3afc8c84c606deac972e577c7dcdfab3f2c4550b 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/WatchAbilitySlice.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/slice/WatchAbilitySlice.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/GsonUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/GsonUtils.java index 22d887d7360ef240511ffd946ec45b7d4b1e00c0..809e3d0c3182fd6d6bbe54355f0cb91e09734013 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/GsonUtils.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/GsonUtils.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * @@ -14,6 +13,7 @@ * limitations under the License. * * + * * Gson is released under the Apache 2.0 license. * * Copyright 2008 Google Inc. diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/HttpUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/HttpUtils.java index b0051055f9fd7094e0b070f32b79958d449c6923..cb11ff029a43e56179e8f82c7a31dfba489c6a47 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/HttpUtils.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/HttpUtils.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * @@ -28,10 +27,12 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.net.HttpURLConnection; import java.net.URL; -import java.net.URLConnection; import java.nio.charset.StandardCharsets; +import javax.net.ssl.HttpsURLConnection; + /** * 网络请求管理类 * @@ -40,8 +41,6 @@ import java.nio.charset.StandardCharsets; public class HttpUtils { private static final String TAG = HttpUtils.class.getName(); - private static final int TIME_OUT = 5 * 1000; - private static HttpUtils instance; private Context context; @@ -78,7 +77,7 @@ public class HttpUtils { * @param callback callback */ public void get(String url, ResponseCallback callback) { - if (Const.MAP_KAY.isEmpty()) { + if (Const.MAP_KEY.isEmpty()) { showError("MAP_KAY cannot be empty"); } else { globalTaskDispatcher.asyncDispatch(() -> { @@ -99,14 +98,21 @@ public class HttpUtils { * @throws IOException */ private void doGet(String address, ResponseCallback callback) throws IOException { + LogUtils.info(TAG, "doGet:"); InputStream inputStream = null; InputStreamReader inputStreamReader = null; BufferedReader bufferedReader = null; try { URL url = new URL(address); - URLConnection connection = url.openConnection(); - connection.setConnectTimeout(TIME_OUT); - inputStream = connection.getInputStream(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + int responseCode = connection.getResponseCode(); + if (responseCode == HttpsURLConnection.HTTP_OK) { + inputStream = connection.getInputStream(); + } else { + doGet(address, callback); + return; + } inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); bufferedReader = new BufferedReader(inputStreamReader); String line; diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ImageUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ImageUtils.java index d6b78c3abfd261babc65b4fe3b6b0ec2350712d5..a7c1f705bffd6d5013fca7876ae1c5df4f1180f1 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ImageUtils.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ImageUtils.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/LogUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/LogUtils.java index 56cbbd498e01e3a8d105590459e0d04ca2eca31a..ad4516beb57607448e83f6abd21c3693099a7ea8 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/LogUtils.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/LogUtils.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/MapUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/MapUtils.java index a79ba29de84fb93c4ed2c996c1c85fe3aead04b4..a0bebedad59b908bb26e2a01165139c0f4dea4e6 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/MapUtils.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/MapUtils.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/PermissionsUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/PermissionsUtils.java index 37376ecef71015b4f620fed6f83081544d1bb7aa..2f4497ef1b2bfcc18b9d56c8ef45b4975e7718af 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/PermissionsUtils.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/PermissionsUtils.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ScreenUtils.java b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ScreenUtils.java index 3c7fb462da3f9f609b6b7d1c32fb2d81698f000c..60ada4f4c1e332a0a82181655eead472f1f0e7d7 100644 --- a/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ScreenUtils.java +++ b/DistributedMapDemo/entry/src/main/java/com/huawei/codelab/util/ScreenUtils.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); + * 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 * diff --git a/DistributedMapDemo/gradle/wrapper/gradle-wrapper.properties b/DistributedMapDemo/gradle/wrapper/gradle-wrapper.properties index 6623300bebd011bc5f7991f4f9c389e2f67b14ac..f59159e865d4b59feb1b8c44b001f62fc5d58df4 100644 --- a/DistributedMapDemo/gradle/wrapper/gradle-wrapper.properties +++ b/DistributedMapDemo/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +distributionUrl=https\://repo.huaweicloud.com/gradle/gradle-6.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/DistributedVideoCodelab/LICENSE b/DistributedVideoCodelab/LICENSE index 80576ef141485b36eea4aebf25af97020bc2de44..7c357dc828cf7d8c783f10ed6bb1bac8a1e903c1 100644 --- a/DistributedVideoCodelab/LICENSE +++ b/DistributedVideoCodelab/LICENSE @@ -1,10 +1,10 @@ - Copyright (c) 2021 Huawei Device Co., Ltd. All rights reserved. + Copyright (c) 2021 Huawei Device Co., Ltd. - Licensed under the Apache License, Version 2.0 (the "License"); + 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 + 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, diff --git a/DistributedVideoCodelab/README.md b/DistributedVideoCodelab/README.md index 14cb9adb252b8aeaf9bfaed44e153d94d71d5cf2..57bd95171b12f11ccfeeae6e38e45d8d2d59f6f3 100644 --- a/DistributedVideoCodelab/README.md +++ b/DistributedVideoCodelab/README.md @@ -1,29 +1,46 @@ -DistributedVideoCodelab - +# DistributedVideoCodelab 简介 -此应用程序展示了视频跨设备迁移的功能。 -您可以通过该应用程序轻松播放来自本地或网络的视频。 -您可以开始播放,暂停,前进,后退等。 -不仅如此,您还可以将视频迁移到局域网(LAN)上的其他设备。 -您可以通过控制对话框控制迁移的视频。 -该示例代码是一个完整的示例,您可以从头开始学习。 +• 此Demo用于跨设备迁移视频内容。您可以方便地跨设备迁移视频内容,然后在源设备远程控制、操作远端设备视频内容。 安装要求 -• 安装DevEco Studio和Node.js -• 设置DevEco Studio开发环境。 DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: - 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK - 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 +• 安装DevEco Studio +• 设置DevEco Studio开发环境。DevEco Studio开发环境需要连接到网络,以确保该正常使用。可以根据以下两种情况配置开发环境: + 1.如果您可以直接访问Internet,则只需下载HarmonyOS SDK + 2.如果网络无法直接访问Internet,则可以通过代理服务器进行访问 • 生成密钥并申请证书 用户指南 • 下载此项目 -• 打开HUAWEI DevEco Studio,单击File> Open选择此ComponentCodelab +• 打开HUAWEI DevEco Studio,单击File> Open选择此项目 • 单击Build> Build App(s)/Hap(s)>Build Debug Hap(s)以编译hap软件包 • 单击Run> Run 'entry'以运行hap包 注意 -• 您可以选择在模拟器或真机上运行hap软件包。 +• 您可以选择在模拟器或真机上运行hap软件包。 • 如果在真机上运行它,则需要在项目的File> Project Structure> Modules> Signing Configs中配置签名和证书信息。 - + 许可 -请参阅LICENSE文件以获得更多信息。 \ No newline at end of file +请参阅LICENSE文件以获得更多信息。 + +What is it? +This demo is used to migrate video content across devices. You can easily migrate video content across devices and remotely control and operate video content on the source device. + +Installation requirements +• Install DevEco Studio +• Set up the DevEco Studio development environment.The DevEco Studio development environment needs to depend on the network environment. It needs to be connected to the network to ensure the normal use of the tool.The development environment can be configured according to the following two situations + 1.If you can directly access the Internet, just download the HarmonyOS SDK + 2.If the network cannot access the Internet directly, it can be accessed through a proxy server +• Generate secret key and apply for certificate + +User guide +• Download this Project +• Open HUAWEI DevEco Studio, click File> Open> Then select and open this Project +• Click Build> Build App(s)/Hap(s)>Build Debug Hap(s) to compile the hap package +• Click Run> Run 'entry' to run the hap package + +Note +• You can choose to run the hap package on the simulator or the phone. +• If you run it on the phone, you need to configure the signature and certificate information in the project's File> Project Structure> Modules> Signing Configs. + +Licensing +Please see LICENSE for more info. \ No newline at end of file diff --git a/DistributedVideoCodelab/build.gradle b/DistributedVideoCodelab/build.gradle index 1ac035e6a21dc7fd8ae73f0e465dc6ef2bbc9c04..cee07328749cf41637db2e71b7fbf43f6bde41e4 100644 --- a/DistributedVideoCodelab/build.gradle +++ b/DistributedVideoCodelab/build.gradle @@ -2,36 +2,36 @@ apply plugin: 'com.huawei.ohos.app' ohos { - compileSdkVersion 3 + compileSdkVersion 5 defaultConfig { - compatibleSdkVersion 3 + compatibleSdkVersion 4 } } - + buildscript { repositories { maven { - url 'https://mirrors.huaweicloud.com/repository/maven/' + url 'https://repo.huaweicloud.com/repository/maven/' } maven { url 'https://developer.huawei.com/repo/' } - jcenter() + jcenter() } dependencies { - classpath 'com.huawei.ohos:hap:2.0.0.6' - + classpath 'com.huawei.ohos:hap:2.4.2.7' + classpath 'com.huawei.ohos:decctest:1.0.0.7' } } allprojects { repositories { maven { - url 'https://mirrors.huaweicloud.com/repository/maven/' + url 'https://repo.huaweicloud.com/repository/maven/' } maven { url 'https://developer.huawei.com/repo/' } - jcenter() + jcenter() } } diff --git a/DistributedVideoCodelab/entry/build.gradle b/DistributedVideoCodelab/entry/build.gradle index 17b0965f34d1a6735bb786288e36c7e9b69d6c6e..95059698209dd4e70219f28daef063de0a9cde67 100644 --- a/DistributedVideoCodelab/entry/build.gradle +++ b/DistributedVideoCodelab/entry/build.gradle @@ -1,12 +1,25 @@ apply plugin: 'com.huawei.ohos.hap' +apply plugin: 'com.huawei.ohos.decctest' ohos { - compileSdkVersion 3 + compileSdkVersion 5 defaultConfig { - compatibleSdkVersion 3 + compatibleSdkVersion 4 + } + buildTypes { + release { + proguardOpt { + proguardEnabled false + rulesFiles 'proguard-rules.pro' + } + } } } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - testCompile'junit:junit:4.12' + implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) + testImplementation 'junit:junit:4.13' + ohosTestImplementation 'com.huawei.ohos.testkit:runner:1.0.0.100' +} +decc { + supportType = ['html','xml'] } diff --git a/DistributedVideoCodelab/entry/src/main/config.json b/DistributedVideoCodelab/entry/src/main/config.json index 0c0361ca6a58c684dbf9ec57dff553b12b5a0cb0..83bff4681882ae4ac3725899a624d22e824feef5 100644 --- a/DistributedVideoCodelab/entry/src/main/config.json +++ b/DistributedVideoCodelab/entry/src/main/config.json @@ -1,19 +1,20 @@ { "app": { - "bundleName": "com.huawei.codelab", + "bundleName": "com.huawei.cookbook", "vendor": "huawei", "version": { "code": 1, "name": "1.0" }, "apiVersion": { - "compatible": 3, - "target": 3 + "compatible": 4, + "target": 4, + "releaseType": "Release" } }, "deviceConfig": {}, "module": { - "package": "com.huawei.codelab", + "package": "ohos.codelabs.distributedvideo", "name": ".MainAbility", "reqCapabilities": [ "video_support" @@ -34,23 +35,35 @@ "entity.system.home" ], "actions": [ - "action.system.home", - "action.video.play" + "action.system.home" ] } ], "orientation": "portrait", "formEnabled": false, - "name": "com.huawei.codelab.MainAbility", + "name": "ohos.codelabs.distributedvideo.MainAbility", "icon": "$media:icon", "description": "$string:mainability_description", "label": "DistributedVideo", "type": "page", "launchType": "standard" }, + { + "orientation": "unspecified", + "configChanges": [ + "orientation" + ], + "formEnabled": false, + "name": ".PlayerAbility", + "icon": "$media:icon", + "description": "$string:videodetailabilityslice_description", + "label": "SimplePlayer", + "type": "page", + "launchType": "standard" + }, { "visible": true, - "name": "com.huawei.codelab.VideoMigrateService", + "name": ".VideoMigrateService", "type": "service" } ], diff --git a/DistributedVideoCodelab/entry/src/main/idl/ohos/huawei.codelab/ImplVideoMigration.idl b/DistributedVideoCodelab/entry/src/main/idl/ohos/huawei.codelab/ImplVideoMigration.idl new file mode 100644 index 0000000000000000000000000000000000000000..8c393010ede45dd179b600d3b9e375d73b5e884a --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/idl/ohos/huawei.codelab/ImplVideoMigration.idl @@ -0,0 +1,12 @@ +// ImplVideoMigration.idl + +// Declare any non-default types here with sequenceable or interface statements + +interface com.huawei.codelab.ImplVideoMigration { + + void flyIn([in] int startTimemiles); + + void playControl([in] int controlCode,[in]int extras); + + int flyOut(); +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/MainAbility.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/MainAbility.java new file mode 100644 index 0000000000000000000000000000000000000000..ac99a79132c03f741e8f40c9be722af7e79afc44 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/MainAbility.java @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.bundle.IBundleManager; +import ohos.codelabs.distributedvideo.slice.MainAbilitySlice; + +/** + * the main page + * + * @since 2020-12-04 + * + */ +public class MainAbility extends Ability { + private static final String PERMISSION_DATASYNC = "ohos.permission.DISTRIBUTED_DATASYNC"; + private static final int MY_PERMISSION_REQUEST_CODE = 1; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + if (verifySelfPermission(PERMISSION_DATASYNC) != IBundleManager.PERMISSION_GRANTED) { + if (canRequestPermission(PERMISSION_DATASYNC)) { + requestPermissionsFromUser(new String[] {PERMISSION_DATASYNC}, MY_PERMISSION_REQUEST_CODE); + } + } + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/PlayerAbility.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/PlayerAbility.java new file mode 100644 index 0000000000000000000000000000000000000000..63844dc7f1aa465b90a85295a16708225ed38e78 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/PlayerAbility.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.codelabs.distributedvideo.slice.SimplePlayerAbilitySlice; + +/** + * the main page + * + * @since 2020-12-04 + * + */ +public class PlayerAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(SimplePlayerAbilitySlice.class.getName()); + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/VideoMigrateService.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/VideoMigrateService.java new file mode 100644 index 0000000000000000000000000000000000000000..ef352fc117374fa3664c0402e4764d85e01b281b --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/VideoMigrateService.java @@ -0,0 +1,116 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; +import ohos.aafwk.content.Operation; +import ohos.codelabs.distributedvideo.manager.idl.VideoMigrationStub; +import ohos.codelabs.distributedvideo.player.api.ImplPlayer; +import ohos.codelabs.distributedvideo.player.constant.Constants; +import ohos.codelabs.distributedvideo.player.constant.ControlCode; +import ohos.codelabs.distributedvideo.player.constant.PlayerStatu; +import ohos.codelabs.distributedvideo.slice.SimplePlayerAbilitySlice; +import ohos.codelabs.distributedvideo.util.AbilitySliceRouteUtil; +import ohos.codelabs.distributedvideo.util.LogUtil; +import ohos.rpc.IRemoteObject; +import ohos.rpc.RemoteException; + +/** + * VideoMigrateService + * + * @since 2020-12-04 + */ +public class VideoMigrateService extends Ability { + private static final String DESCRIPTOR = "com.huawei.codelab.ImplVideoMigration"; + private static final String TAG = VideoMigrateService.class.getName(); + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + } + + @Override + protected IRemoteObject onConnect(Intent intent) { + return new MyBinder(DESCRIPTOR); + } + + /** + * MyBinder + * + * @since 2020-12-04 + */ + private class MyBinder extends VideoMigrationStub { + /** + * constructor of PlayerLoading + * + * @param descriptor descriptor + */ + MyBinder(String descriptor) { + super(descriptor); + } + + @Override + public void flyIn(int startTimemiles) throws RemoteException { + Intent intent = new Intent(); + Operation operation = new Intent.OperationBuilder().withBundleName(getBundleName()) + .withAbilityName(PlayerAbility.class.getName()).build(); + intent.setOperation(operation); + intent.setParam(Constants.INTENT_STARTTIME_PARAM, startTimemiles); + startAbility(intent); + } + + @Override + public void playControl(int controlCode, int extras) throws RemoteException { + ImplPlayer player = SimplePlayerAbilitySlice.getImplPlayer(); + if (player != null) { + if (controlCode == ControlCode.RESUME.getCode()) { + if (player.getPlayerStatu() == PlayerStatu.STOP + || player.getPlayerStatu() == PlayerStatu.COMPLETE) { + player.replay(); + } else { + player.resume(); + } + } else if (controlCode == ControlCode.PAUSE.getCode()) { + player.pause(); + } else if (controlCode == ControlCode.STOP.getCode()) { + player.stop(); + } else if (controlCode == ControlCode.SEEK.getCode()) { + player.rewindTo(player.getDuration() * extras / Constants.ONE_HUNDRED_PERCENT); + } else if (controlCode == ControlCode.FORWARD.getCode()) { + player.rewindTo(player.getCurrentPosition() + Constants.REWIND_STEP); + } else if (controlCode == ControlCode.REWARD.getCode()) { + player.rewindTo(player.getCurrentPosition() - Constants.REWIND_STEP); + } else if (controlCode == ControlCode.VOLUME_SET.getCode()) { + player.setVolume(extras / Constants.ONE_HUNDRED_PERCENT_FLOAT); + } else if (controlCode == ControlCode.VOLUME_ADD.getCode()) { + player.setVolume(player.getVolume() + Constants.VOLUME_STEP); + } else if (controlCode == ControlCode.VOLUME_REDUCED.getCode()) { + float volume = player.getVolume() - Constants.VOLUME_STEP; + player.setVolume(volume < 0 ? 0 : Math.min(1, volume)); + } else { + LogUtil.info(TAG, "playControl else message"); + } + } + } + + @Override + public int flyOut() throws RemoteException { + AbilitySliceRouteUtil.getInstance().terminateSlices(); + return SimplePlayerAbilitySlice.getImplPlayer().getCurrentPosition(); + } + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/component/RemoteController.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/component/RemoteController.java new file mode 100644 index 0000000000000000000000000000000000000000..c7d7e9296f21fa01ffde8c19a3979f64cc0754b0 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/component/RemoteController.java @@ -0,0 +1,254 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.component; + +import ohos.agp.components.Button; +import ohos.agp.components.Component; +import ohos.agp.components.DependentLayout; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.Slider; +import ohos.app.Context; +import ohos.codelabs.distributedvideo.ResourceTable; +import ohos.codelabs.distributedvideo.player.constant.Constants; +import ohos.codelabs.distributedvideo.player.constant.ControlCode; +import ohos.codelabs.distributedvideo.util.ScreenUtils; +import ohos.multimodalinput.event.TouchEvent; + +/** + * RemoteController + * + * @since 2020-12-04 + */ +public class RemoteController extends DependentLayout + implements Component.ClickedListener, Component.TouchEventListener, Slider.ValueChangedListener { + private static final int TOAST_DURATION = 3000; + private static final float ALPHA = 0.7f; + private Context context; + private RemoteControllerListener remoteControllerListener; + private Component componentParent; + private boolean isShown = false; + private boolean isStop = false; + private int controlCode = 0; + private int controlNumber = 0; + + /** + * constructor of RemoteController + * + * @param context context + */ + public RemoteController(Context context) { + super(context); + this.context = context; + initView(); + } + + /** + * init RemoteController view + */ + public void initView() { + setVisibility(INVISIBLE); + componentParent = LayoutScatter.getInstance(context).parse( + ResourceTable.Layout_remote_controller, + this, + false); + initButton(ResourceTable.Id_remote_resume); + initButton(ResourceTable.Id_remote_pause); + initButton(ResourceTable.Id_remote_stop); + initButton(ResourceTable.Id_remote_forward); + initButton(ResourceTable.Id_remote_reward); + initButton(ResourceTable.Id_remote_volume_up); + initButton(ResourceTable.Id_remote_volume_down); + if (componentParent.findComponentById(ResourceTable.Id_remote_progress_seek) instanceof Slider) { + Slider progressSlider = (Slider) componentParent.findComponentById(ResourceTable.Id_remote_progress_seek); + progressSlider.setValueChangedListener(this); + } + if (componentParent.findComponentById(ResourceTable.Id_remote_volume_seek) instanceof Slider) { + Slider volumeSlider = (Slider) componentParent.findComponentById(ResourceTable.Id_remote_volume_seek); + volumeSlider.setMinValue(0); + volumeSlider.setMaxValue(Constants.NUMBER_100); + volumeSlider.setValueChangedListener(this); + } + setWidth(ScreenUtils.getScreenWidth(context)); + setHeight(ScreenUtils.getScreenHeight(context)); + addComponent(componentParent); + } + + private void initButton(int res) { + Button button = null; + if (componentParent.findComponentById(res) instanceof Button) { + button = (Button) componentParent.findComponentById(res); + } + button.setClickedListener(this); + button.setTouchEventListener(this); + button.setAlpha(ALPHA); + } + + /** + * show method + */ + public void show() { + if (!isShown) { + isShown = true; + setVisibility(VISIBLE); + if (remoteControllerListener != null) { + remoteControllerListener.controllerShow(); + } + } + } + + /** + * hide method + */ + public void hide() { + if (isShown) { + isShown = false; + setVisibility(INVISIBLE); + if (remoteControllerListener != null) { + remoteControllerListener.controllerDismiss(); + } + } + } + + /** + * isShown + * + * @return boolean isShown + */ + public boolean isShown() { + return isShown; + } + + /** + * setRemoteControllerCallback + * + * @param listener listener + */ + public void setRemoteControllerCallback(RemoteControllerListener listener) { + remoteControllerListener = listener; + } + + /** + * RemoteControllerListener + * + * @since 2020-12-07 + */ + public interface RemoteControllerListener { + /** + * show the controller dialog + * + * @since 2020-12-07 + */ + void controllerShow(); + + /** + * dismiss the controller dialog + * + * @since 2020-12-07 + */ + void controllerDismiss(); + + /** + * sendControl + * + * @param code code + * @param extra extra + */ + void sendControl(int code, int extra); + } + + @Override + public boolean onTouchEvent(Component component, TouchEvent touchEvent) { + switch (touchEvent.getAction()) { + case TouchEvent.PRIMARY_POINT_DOWN: + component.setAlpha(1); + break; + case TouchEvent.PRIMARY_POINT_UP: + component.setAlpha(ALPHA); + break; + default: + break; + } + return true; + } + + @Override + public void onClick(Component component) { + if (component.getId() != ResourceTable.Id_remote_resume && isStop) { + Toast.toast(context, "Please play video first.", TOAST_DURATION); + return; + } + switch (component.getId()) { + case ResourceTable.Id_remote_resume: + isStop = false; + controlCode = ControlCode.RESUME.getCode(); + break; + case ResourceTable.Id_remote_stop: + isStop = true; + controlCode = ControlCode.STOP.getCode(); + break; + case ResourceTable.Id_remote_forward: + controlCode = ControlCode.FORWARD.getCode(); + break; + case ResourceTable.Id_remote_pause: + controlCode = ControlCode.PAUSE.getCode(); + break; + case ResourceTable.Id_remote_reward: + controlCode = ControlCode.REWARD.getCode(); + break; + case ResourceTable.Id_remote_volume_up: + controlCode = ControlCode.VOLUME_ADD.getCode(); + break; + case ResourceTable.Id_remote_volume_down: + controlCode = ControlCode.VOLUME_REDUCED.getCode(); + break; + default: + break; + } + if (remoteControllerListener != null) { + remoteControllerListener.sendControl(controlCode, 0); + } + } + + @Override + public void onProgressUpdated(Slider slider, int extra, boolean isUpdate) { + } + + @Override + public void onTouchStart(Slider slider) { + } + + @Override + public void onTouchEnd(Slider slider) { + if (isStop) { + Toast.toast(context, "Please play video first.", TOAST_DURATION); + return; + } + int extras = slider.getProgress(); + switch (slider.getId()) { + case ResourceTable.Id_remote_progress_seek: + controlNumber = ControlCode.SEEK.getCode(); + break; + case ResourceTable.Id_remote_volume_seek: + controlNumber = ControlCode.VOLUME_SET.getCode(); + break; + default: + break; + } + if (remoteControllerListener != null) { + remoteControllerListener.sendControl(controlNumber, extras); + } + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/component/SlidePopupWindow.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/component/SlidePopupWindow.java new file mode 100644 index 0000000000000000000000000000000000000000..2c6ab6fdac91d9488457a45f970baa6b214ff484 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/component/SlidePopupWindow.java @@ -0,0 +1,330 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.component; + +import ohos.agp.animation.Animator; +import ohos.agp.animation.AnimatorProperty; +import ohos.agp.colors.RgbColor; +import ohos.agp.components.Component; +import ohos.agp.components.DependentLayout; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.element.ShapeElement; +import ohos.app.Context; +import ohos.codelabs.distributedvideo.player.constant.Constants; +import ohos.codelabs.distributedvideo.util.ScreenUtils; +import ohos.multimodalinput.event.TouchEvent; + +/** + * SlidePopupWindow + * + * @since 2020-12-04 + */ +public class SlidePopupWindow extends DependentLayout implements Component.TouchEventListener { + /** + * SLIDE FROM TOP + */ + public static final int SLIDE_FROM_TOP = 0; + /** + * SLIDE FROM BOTTOM + */ + public static final int SLIDE_FROM_BOTTOM = 1; + /** + * SLIDE FROM LEFT + */ + public static final int SLIDE_FROM_LEFT = 2; + /** + * SLIDE FROM RIGHT + */ + public static final int SLIDE_FROM_RIGHT = 3; + + private static final int COLOR_FULL = 255; + private Builder mBuilder; + private Component mRootView; + private AnimatorProperty animatorProperty; + private int startX = 0; + private int endX = 0; + private int startY = 0; + private int endY = 0; + private boolean isShow; + private PopupWindowListener mListener; + + private SlidePopupWindow(Builder builder, int res) { + super(builder.mContext); + mBuilder = builder; + mRootView = LayoutScatter.getInstance(builder.mContext).parse(res, this, false); + animatorProperty = mRootView.createAnimatorProperty(); + initView(); + initListener(); + } + + private SlidePopupWindow(Builder builder, Component rootView) { + super(builder.mContext); + mBuilder = builder; + mRootView = rootView; + animatorProperty = mRootView.createAnimatorProperty(); + initView(); + initListener(); + } + + private void initView() { + setVisibility(HIDE); + setWidth(ScreenUtils.getScreenWidth(mContext)); + setHeight(ScreenUtils.getScreenHeight(mContext) - Constants.NUMBER_168); + ShapeElement element = new ShapeElement(); + element.setRgbColor(new RgbColor(0, 0, 0, (int) (COLOR_FULL * mBuilder.alpha))); + setBackground(element); + LayoutConfig config = (LayoutConfig) mRootView.getLayoutConfig(); + switch (mBuilder.direction) { + case SLIDE_FROM_TOP: + config.addRule(LayoutConfig.ALIGN_PARENT_TOP); + config.setMargins(0, -mRootView.getHeight(), 0, 0); + startY = -mRootView.getHeight(); + break; + case SLIDE_FROM_BOTTOM: + config.addRule(LayoutConfig.ALIGN_PARENT_BOTTOM); + config.setMargins(0, 0, 0, -mRootView.getHeight()); + startY = getHeight(); + endY = getHeight() - mRootView.getHeight(); + break; + case SLIDE_FROM_LEFT: + config.addRule(LayoutConfig.ALIGN_PARENT_LEFT); + config.setMargins(-mRootView.getWidth(), 0, 0, 0); + startX = -mRootView.getWidth(); + break; + case SLIDE_FROM_RIGHT: + config.addRule(LayoutConfig.ALIGN_PARENT_RIGHT); + config.setMargins(0, 0, -mRootView.getWidth(), 0); + startX = getWidth(); + endX = getWidth() - mRootView.getWidth(); + break; + default: + break; + } + mRootView.setLayoutConfig(config); + mRootView.setTouchEventListener((component, touchEvent) -> true); + addComponent(mRootView); + } + + private void initListener() { + setTouchEventListener(this); + animatorProperty.setStateChangedListener(new MyAnimatorStateChangeListener()); + } + + /** + * MyAnimatorStateChangeListener + * + * @since 2020-12-04 + */ + private class MyAnimatorStateChangeListener implements Animator.StateChangedListener { + @Override + public void onStart(Animator animator) { + if (isShow) { + if (mListener != null) { + mListener.windowShow(); + } + setVisibility(VISIBLE); + } + } + + @Override + public void onStop(Animator animator) { + } + + @Override + public void onCancel(Animator animator) { + } + + @Override + public void onEnd(Animator animator) { + if (!isShow) { + setVisibility(INVISIBLE); + if (mListener != null) { + mListener.windowDismiss(); + } + } + } + + @Override + public void onPause(Animator animator) { + } + + @Override + public void onResume(Animator animator) { + } + } + + /** + * PopupWindowListener + * + * @since 2020-12-04 + */ + public interface PopupWindowListener { + /** + * windowShow + */ + void windowShow(); + + /** + * windowDismiss + */ + void windowDismiss(); + } + + /** + * setPopupWindowListener + * + * @param listener listener + */ + public void setPopupWindowListener(PopupWindowListener listener) { + mListener = listener; + } + + @Override + public boolean onTouchEvent(Component component, TouchEvent touchEvent) { + hide(); + return true; + } + + /** + * show of SlidePopupWindow + */ + public void show() { + if (!isShow) { + isShow = true; + animatorProperty + .moveFromX(startX) + .moveToX(endX) + .moveFromY(startY) + .moveToY(endY) + .setCurveType(Animator.CurveType.LINEAR) + .setDuration(mBuilder.animDuration) + .start(); + } + } + + /** + * hide of SlidePopupWindow + */ + public void hide() { + if (isShow) { + isShow = false; + animatorProperty + .moveFromX(endX) + .moveToX(startX) + .moveFromY(endY) + .moveToY(startY) + .setCurveType(Animator.CurveType.LINEAR) + .setDuration(mBuilder.animDuration) + .start(); + } + } + + /** + * Builder + * + * @author chenweiquan + * @since 2020-12-04 + */ + public static class Builder { + private static final float ALPHA_DEFAULT = 0.5f; + private static final int ANIM_DURATION = 300; + private Context mContext; + private float alpha; + private int animDuration; + private int direction; + + /** + * constructor of Builder + * + * @param context builder + */ + public Builder(Context context) { + this.mContext = context; + alpha = ALPHA_DEFAULT; + animDuration = ANIM_DURATION; + direction = SLIDE_FROM_BOTTOM; + } + + public float getAlpha() { + return alpha; + } + + /** + * setAlpha of Builder + * + * @param alpha alpha + * @return Builder + */ + public Builder setAlpha(float alpha) { + if (alpha > 1) { + this.alpha = 1; + } else { + this.alpha = Math.max(0, alpha); + } + return this; + } + + public int getAnimDuration() { + return animDuration; + } + + /** + * setAnimDuration of Builder + * + * @param animDuration animDuration + * @return Builder + */ + public Builder setAnimDuration(int animDuration) { + this.animDuration = animDuration; + return this; + } + + public int getDirection() { + return direction; + } + + /** + * setDirection of Builder + * + * @param direction direction + * @return Builder + */ + public Builder setDirection(int direction) { + this.direction = direction; + return this; + } + + /** + * getView of Builder + * + * @param res res + * @return SlidePopupWindow + */ + public SlidePopupWindow create(int res) { + return new SlidePopupWindow(this, res); + } + + /** + * getView of Builder + * + * @param component res + * @return SlidePopupWindow + */ + public SlidePopupWindow create(Component component) { + return new SlidePopupWindow(this, component); + } + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/component/Toast.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/component/Toast.java new file mode 100644 index 0000000000000000000000000000000000000000..e25bd13a360955a14ebbdcd5a0f7aa307c92443e --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/component/Toast.java @@ -0,0 +1,79 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.component; + +import ohos.agp.colors.RgbColor; +import ohos.agp.components.DependentLayout; +import ohos.agp.components.Text; +import ohos.agp.components.element.ShapeElement; +import ohos.agp.utils.Color; +import ohos.agp.window.dialog.ToastDialog; +import ohos.app.Context; +import ohos.codelabs.distributedvideo.util.ScreenUtils; + +/** + * Toast + * + * @since 2020-12-04 + */ +public class Toast { + private static final int TEXT_SIZE = 40; + private static final int TEXT_PADDING = 20; + private static final int TEXT_HEIGHT = 100; + private static final int TEXT_CORNER = 20; + private static final int TEXT_OFFSETY = 200; + private static final int TEXT_ALPHA = 120; + + private Toast() { + } + + /** + * toast + * + * @param context the context + * @param text the toast content + * @param ms the toast ime,ms + */ + public static void toast(Context context, String text, int ms) { + DependentLayout layout = new DependentLayout(context); + layout.setWidth(ScreenUtils.getScreenWidth(context)); + layout.setHeight(TEXT_HEIGHT); + Text textView = new Text(context); + ShapeElement background = new ShapeElement(); + background.setCornerRadius(TEXT_CORNER); + background.setRgbColor(new RgbColor(0, 0, 0, TEXT_ALPHA)); + textView.setBackground(background); + DependentLayout.LayoutConfig config = + new DependentLayout.LayoutConfig( + DependentLayout.LayoutConfig.MATCH_CONTENT, DependentLayout.LayoutConfig.MATCH_CONTENT); + config.addRule(DependentLayout.LayoutConfig.HORIZONTAL_CENTER); + textView.setLayoutConfig(config); + textView.setPadding(TEXT_PADDING, TEXT_PADDING, TEXT_PADDING, TEXT_PADDING); + textView.setMaxTextLines(1); + textView.setTextSize(TEXT_SIZE); + textView.setMaxTextWidth(ScreenUtils.getScreenWidth(context)); + textView.setTextColor(Color.WHITE); + textView.setText(text); + layout.addComponent(textView); + ToastDialog toastDialog = new ToastDialog(context); + toastDialog.setContentCustomComponent(layout); + toastDialog.setTransparent(true); + toastDialog.setOffset(0, TEXT_OFFSETY); + toastDialog.setSize(ScreenUtils.getScreenWidth(context), TEXT_HEIGHT); + toastDialog.setDuration(ms); + toastDialog.show(); + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/data/AdvertisementMo.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/data/AdvertisementMo.java new file mode 100644 index 0000000000000000000000000000000000000000..e20664874054f1401ac9680b6fcc1f64ae59d341 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/data/AdvertisementMo.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.data; + +/** + * AdvertisementMo object + * + * @since 2020-12-04 + * + */ +public class AdvertisementMo { + private int sourceId; + + private String description; + + /** + * constructor + * + * @param sourceId graphic id + * @param description advertisement description + */ + public AdvertisementMo(int sourceId, String description) { + this.sourceId = sourceId; + this.description = description; + } + + public int getSourceId() { + return sourceId; + } + + public void setSourceId(int sourceId) { + this.sourceId = sourceId; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/data/VideoListMo.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/data/VideoListMo.java new file mode 100644 index 0000000000000000000000000000000000000000..e0e0cc849bb11d76d4d36d86f1b2c7149aeade62 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/data/VideoListMo.java @@ -0,0 +1,67 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.data; + +/** + * VideoList object + * + * @since 2020-12-04 + * + */ +public class VideoListMo { + private int sourceId; + + private String name; + + private String description; + + /** + * VideoListMo + * + * @param sourceId sourceId + * @param name name + * @param description description + */ + public VideoListMo(int sourceId, String name, String description) { + this.sourceId = sourceId; + this.name = name; + this.description = description; + } + + public int getSourceId() { + return sourceId; + } + + public void setSourceId(int sourceId) { + this.sourceId = sourceId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/data/VideoTabStyle.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/data/VideoTabStyle.java new file mode 100644 index 0000000000000000000000000000000000000000..661a9685046e09f34a06daa6ab32242769d2382d --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/data/VideoTabStyle.java @@ -0,0 +1,61 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.data; + +/** + * Video Component style + * + * @since 2020-12-04 + */ +public class VideoTabStyle { + /** + * BOLD FONT NAME + * + */ + public static final String BOLD_FONT_NAME = "微软雅黑"; + /** + * INDICATOR OFFSET + * + */ + public static final int INDICATOR_OFFSET = 12; + /** + * INDICATOR NORMA ALPHA + * + */ + public static final int INDICATOR_NORMA_ALPHA = 168; + /** + * INDICATOR BONDS + * + */ + public static final int INDICATOR_BONDS = 20; + /** + * ADVERTISEMENT SLID PROID + * + */ + public static final int ADVERTISEMENT_SLID_PROID = 3; + /** + * ADVERTISEMENT SLID DELAY + * + */ + public static final int ADVERTISEMENT_SLID_DELAY = 3; + + /** + * constructor of VideoTabStyle + * + */ + private VideoTabStyle() { + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/manager/idl/ImplVideoMigration.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/manager/idl/ImplVideoMigration.java new file mode 100644 index 0000000000000000000000000000000000000000..3fc9e21ca3ba319bc4b13cac701e02acd609b66a --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/manager/idl/ImplVideoMigration.java @@ -0,0 +1,57 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.manager.idl; + +import ohos.rpc.IRemoteBroker; +import ohos.rpc.RemoteException; + +/** + * the main page + * + * @since 2020-12-04 + * + */ + +public interface ImplVideoMigration extends IRemoteBroker { + /** + * flyIn + * + * @param startTimemiles startTimemiles + * @throws RemoteException RemoteException + */ + void flyIn( + /* [in] */ int startTimemiles) throws RemoteException; + + /** + * playControl + * + * @param controlCode controlCode + * @param extras extras + * @throws RemoteException RemoteException + */ + void playControl( + /* [in] */ int controlCode, + /* [in] */ int extras) throws RemoteException; + + /** + * flyOut + * + * @return rturn the status code + * @throws RemoteException RemoteException + */ + int flyOut() throws RemoteException; +} + diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/manager/idl/VideoMigrationProxy.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/manager/idl/VideoMigrationProxy.java new file mode 100644 index 0000000000000000000000000000000000000000..c5fa64bf11d46097772e9b7628cb0cb6410d5584 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/manager/idl/VideoMigrationProxy.java @@ -0,0 +1,113 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.manager.idl; + +import ohos.rpc.IRemoteObject; +import ohos.rpc.MessageOption; +import ohos.rpc.MessageParcel; +import ohos.rpc.RemoteException; + +/** + * the main page + * + * @since 2020-12-04 + * + */ +public class VideoMigrationProxy implements ImplVideoMigration { + private static final String DESCRIPTOR = "com.huawei.codelab.ImplVideoMigration"; + private static final int COMMAND_FLY_IN = IRemoteObject.MIN_TRANSACTION_ID + 0; + private static final int COMMAND_PLAY_CONTROL = IRemoteObject.MIN_TRANSACTION_ID + 1; + private static final int COMMAND_FLY_OUT = IRemoteObject.MIN_TRANSACTION_ID + 2; + private static final int ERR_OK = 0; + private static final String TAG = "VideoMigrationProxy"; + + private final IRemoteObject remote; + + /** + * constructor of VideoMigrationProxy + * + * @param remote remote + */ + public VideoMigrationProxy( + /* [in] */ IRemoteObject remote) { + this.remote = remote; + } + + @Override + public IRemoteObject asObject() { + return remote; + } + + @Override + public void flyIn( + + /* [in] */ int startTimemiles) throws RemoteException { + MessageParcel data = MessageParcel.obtain(); + MessageParcel reply = MessageParcel.obtain(); + MessageOption option = new MessageOption(MessageOption.TF_SYNC); + + data.writeInterfaceToken(DESCRIPTOR); + data.writeInt(startTimemiles); + + try { + remote.sendRequest(COMMAND_FLY_IN, data, reply, option); + reply.readException(); + } finally { + data.reclaim(); + reply.reclaim(); + } + } + + @Override + public void playControl( + /* [in] */ int controlCode, + /* [in] */ int extras) throws RemoteException { + MessageParcel data = MessageParcel.obtain(); + MessageParcel reply = MessageParcel.obtain(); + MessageOption option = new MessageOption(MessageOption.TF_SYNC); + + data.writeInterfaceToken(DESCRIPTOR); + data.writeInt(controlCode); + data.writeInt(extras); + + try { + remote.sendRequest(COMMAND_PLAY_CONTROL, data, reply, option); + reply.readException(); + } finally { + data.reclaim(); + reply.reclaim(); + } + } + + @Override + public int flyOut() throws RemoteException { + MessageParcel data = MessageParcel.obtain(); + MessageParcel reply = MessageParcel.obtain(); + MessageOption option = new MessageOption(MessageOption.TF_SYNC); + + data.writeInterfaceToken(DESCRIPTOR); + try { + remote.sendRequest(COMMAND_FLY_OUT, data, reply, option); + reply.readException(); + int result = reply.readInt(); + return result; + } finally { + data.reclaim(); + reply.reclaim(); + } + } +} + diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/manager/idl/VideoMigrationStub.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/manager/idl/VideoMigrationStub.java new file mode 100644 index 0000000000000000000000000000000000000000..6f404bfe08d37d56a9f711a8fcc246c17dc270f2 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/manager/idl/VideoMigrationStub.java @@ -0,0 +1,114 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.manager.idl; + +import ohos.rpc.IRemoteBroker; +import ohos.rpc.IRemoteObject; +import ohos.rpc.MessageOption; +import ohos.rpc.MessageParcel; +import ohos.rpc.RemoteException; +import ohos.rpc.RemoteObject; + +/** + * the main page + * + * @since 2020-12-07 + * + */ +public abstract class VideoMigrationStub extends RemoteObject implements ImplVideoMigration { + private static final String DESCRIPTOR = "com.huawei.codelab.ImplVideoMigration"; + private static final String TAG = "VideoMigrationStub"; + private static final int COMMAND_FLY_IN = IRemoteObject.MIN_TRANSACTION_ID + 0; + private static final int COMMAND_PLAY_CONTROL = IRemoteObject.MIN_TRANSACTION_ID + 1; + private static final int COMMAND_FLY_OUT = IRemoteObject.MIN_TRANSACTION_ID + 2; + private static final int ERR_OK = 0; + private static final int ERR_RUNTIME_EXCEPTION = -1; + + /** + * constructor of VideoMigrationStub + * + * @param descriptor descriptor + */ + public VideoMigrationStub( + /* [in] */ String descriptor) { + super(descriptor); + } + + @Override + public IRemoteObject asObject() { + return this; + } + + /** + * Video Migration + * + * @param object IRemoteObject + * @return ImplVideoMigration + */ + public static ImplVideoMigration asInterface(IRemoteObject object) { + ImplVideoMigration result = null; + if (object == null) { + return result; + } + IRemoteBroker broker = object.queryLocalInterface(DESCRIPTOR); + if (broker != null) { + if (broker instanceof ImplVideoMigration) { + result = (ImplVideoMigration)broker; + } + } else { + result = new VideoMigrationProxy(object); + } + + return result; + } + + @Override + public boolean onRemoteRequest( + /* [in] */ int code, + /* [in] */ MessageParcel data, + /* [out] */ MessageParcel reply, + /* [in] */ MessageOption option) throws RemoteException { + String token = data.readInterfaceToken(); + if (!DESCRIPTOR.equals(token)) { + return false; + } + switch (code) { + case COMMAND_FLY_IN: { + int startTimemiles = data.readInt(); + flyIn(startTimemiles); + reply.writeNoException(); + return true; + } + case COMMAND_PLAY_CONTROL: { + int controlCode = data.readInt(); + int extras = data.readInt(); + playControl(controlCode, extras); + reply.writeNoException(); + return true; + } + case COMMAND_FLY_OUT: { + int result; + result = flyOut(); + reply.writeNoException(); + reply.writeInt(result); + return true; + } + default: + return super.onRemoteRequest(code, data, reply, option); + } + } +} + diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/HmPlayer.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/HmPlayer.java new file mode 100644 index 0000000000000000000000000000000000000000..74f513c95c18d099c0c5a75620d6e0e4dd194c5b --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/HmPlayer.java @@ -0,0 +1,507 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player; + +import ohos.agp.graphics.Surface; +import ohos.app.Context; +import ohos.app.dispatcher.task.TaskPriority; +import ohos.codelabs.distributedvideo.player.api.ImplLifecycle; +import ohos.codelabs.distributedvideo.player.api.ImplPlayer; +import ohos.codelabs.distributedvideo.player.api.ScreenChangeListener; +import ohos.codelabs.distributedvideo.player.api.StatuChangeListener; +import ohos.codelabs.distributedvideo.player.constant.Constants; +import ohos.codelabs.distributedvideo.player.constant.PlayerStatu; +import ohos.codelabs.distributedvideo.player.factory.SourceFactory; +import ohos.codelabs.distributedvideo.player.manager.HmPlayerLifecycle; +import ohos.codelabs.distributedvideo.util.LogUtil; +import ohos.media.common.Source; +import ohos.media.player.Player; + +import java.util.ArrayList; +import java.util.List; + +/** + * Hm player + * + * @since 2021-04-04 + */ +public class HmPlayer implements ImplPlayer { + private static final String TAG = HmPlayer.class.getSimpleName(); + private static final int MICRO_MILLI_RATE = 1000; + private Player mPlayer; + private Surface surface; + private HmPlayerLifecycle mLifecycle; + private Builder mBuilder; + private PlayerStatu mStatu = PlayerStatu.IDEL; + private float currentVolume = 1; + private double videoScale = Constants.NUMBER_NEGATIVE_1; + private boolean isGestureOpen; + + private List statuChangeCallbacks = new ArrayList<>(0); + private List screenChangeCallbacks = new ArrayList<>(0); + + /** + * constructor of HmPlayer + * + * @param builder builder + */ + private HmPlayer(Builder builder) { + mBuilder = builder; + mLifecycle = new HmPlayerLifecycle(this); + } + + private void initBasePlayer() { + mPlayer = new Player(mBuilder.mContext); + Source source = new SourceFactory(mBuilder.mContext, mBuilder.filePath).getSource(); + mPlayer.setSource(source); + mPlayer.setPlayerCallback(new HmPlayerCallback()); + } + + /** + * HmPlayer Callback + * + * @since 2020-12-04 + */ + private class HmPlayerCallback implements Player.IPlayerCallback { + @Override + public void onPrepared() { + LogUtil.info(TAG, "onPrepared is called "); + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PREPARED; + callback.statuCallback(PlayerStatu.PREPARED); + } + } + + @Override + public void onMessage(int info, int i1) { + LogUtil.info(TAG, "onMessage info is " + info + ",i1 is" + i1); + if (i1 == 0) { + switch (info) { + case Player.PLAYER_INFO_VIDEO_RENDERING_START: + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PLAY; + callback.statuCallback(PlayerStatu.PLAY); + } + if (mBuilder.isPause) { + pause(); + } + break; + case Player.PLAYER_INFO_BUFFERING_START: + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.BUFFERING; + callback.statuCallback(PlayerStatu.BUFFERING); + } + break; + case Player.PLAYER_INFO_BUFFERING_END: + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PLAY; + callback.statuCallback(PlayerStatu.PLAY); + } + break; + default: + break; + } + } + } + + @Override + public void onError(int type, int extra) { + LogUtil.info(TAG, "onError is called ,i is " + type + ",i1 is " + extra); + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.ERROR; + callback.statuCallback(PlayerStatu.ERROR); + } + release(); + } + + @Override + public void onResolutionChanged(int videoX, int videoY) { + LogUtil.info(TAG, "onResolutionChanged videoX is " + videoX + ",videoY is " + videoY); + if (!mBuilder.isStretch && videoX != 0 && videoY != 0) { + videoScale = (double) videoX / videoY; + } + } + + @Override + public void onPlayBackComplete() { + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.COMPLETE; + callback.statuCallback(PlayerStatu.COMPLETE); + } + } + + @Override + public void onRewindToComplete() { + resume(); + } + + @Override + public void onBufferingChange(int value) { + } + + @Override + public void onNewTimedMetaData(Player.MediaTimedMetaData mediaTimedMetaData) { + LogUtil.info(TAG, "onNewTimedMetaData is called"); + } + + @Override + public void onMediaTimeIncontinuity(Player.MediaTimeInfo mediaTimeInfo) { + LogUtil.info(TAG, "onMediaTimeIncontinuity is called"); + for (Player.StreamInfo streanInfo : mPlayer.getStreamInfo()) { + int streamType = streanInfo.getStreamType(); + if (streamType == Player.StreamInfo.MEDIA_STREAM_TYPE_AUDIO && mStatu == PlayerStatu.PREPARED) { + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PLAY; + callback.statuCallback(PlayerStatu.PLAY); + } + if (mBuilder.isPause) { + pause(); + } + } + } + } + } + + /** + * start time consuming operation + */ + private void start() { + if (mPlayer != null) { + mBuilder.mContext.getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(() -> { + if (surface != null) { + mPlayer.setVideoSurface(surface); + } else { + LogUtil.error(TAG, "The surface has not been initialized."); + } + mPlayer.prepare(); + if (mBuilder.startMillisecond > 0) { + int microsecond = mBuilder.startMillisecond * MICRO_MILLI_RATE; + mPlayer.rewindTo(microsecond); + } + mPlayer.play(); + }); + } + } + + @Override + public ImplLifecycle getLifecycle() { + return mLifecycle; + } + + @Override + public void addSurface(Surface videoSurface) { + this.surface = videoSurface; + } + + @Override + public void addPlayerStatuCallback(StatuChangeListener callback) { + if (callback != null) { + statuChangeCallbacks.add(callback); + } + } + + @Override + public void removePlayerStatuCallback(StatuChangeListener callback) { + statuChangeCallbacks.remove(callback); + } + + @Override + public void addPlayerViewCallback(ScreenChangeListener callback) { + if (callback != null) { + screenChangeCallbacks.add(callback); + } + } + + @Override + public void removePlayerViewCallback(ScreenChangeListener callback) { + screenChangeCallbacks.remove(callback); + } + + @Override + public Builder getBuilder() { + return mBuilder; + } + + @Override + public PlayerStatu getPlayerStatu() { + return mStatu; + } + + @Override + public void resizeScreen(int width, int height) { + for (ScreenChangeListener screenChangeCallback : screenChangeCallbacks) { + screenChangeCallback.screenCallback(width, height); + } + } + + @Override + public void openGesture(boolean isOpen) { + isGestureOpen = isOpen; + } + + @Override + public boolean isGestureOpen() { + return isPlaying() && isGestureOpen; + } + + @Override + public void play() { + if (mPlayer != null) { + mPlayer.reset(); + } + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PREPARING; + callback.statuCallback(PlayerStatu.PREPARING); + } + initBasePlayer(); + start(); + } + + @Override + public void replay() { + if (isPlaying()) { + rewindTo(0); + } else { + reload(mBuilder.filePath, 0); + } + } + + @Override + public void reload(String filepath, int startMillisecond) { + mBuilder.filePath = filepath; + mBuilder.startMillisecond = startMillisecond; + play(); + } + + @Override + public void stop() { + if (mPlayer == null) { + return; + } + mPlayer.stop(); + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.STOP; + callback.statuCallback(PlayerStatu.STOP); + } + } + + @Override + public void release() { + if (mPlayer == null) { + return; + } + if (mStatu != PlayerStatu.IDEL) { + videoScale = Constants.NUMBER_NEGATIVE_1; + mPlayer.release(); + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.IDEL; + callback.statuCallback(PlayerStatu.IDEL); + } + } + } + + @Override + public void resume() { + if (mPlayer == null) { + return; + } + if (mStatu != PlayerStatu.IDEL) { + if (!isPlaying()) { + mPlayer.play(); + } + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PLAY; + callback.statuCallback(PlayerStatu.PLAY); + } + } + } + + @Override + public void pause() { + if (mPlayer == null) { + return; + } + if (isPlaying()) { + mPlayer.pause(); + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.PAUSE; + callback.statuCallback(PlayerStatu.PAUSE); + } + } + } + + @Override + public int getCurrentPosition() { + if (mPlayer == null) { + return 0; + } + return mPlayer.getCurrentTime(); + } + + @Override + public int getDuration() { + if (mPlayer == null) { + return 0; + } + return mPlayer.getDuration(); + } + + @Override + public float getVolume() { + return currentVolume; + } + + @Override + public void setVolume(float volume) { + if (mPlayer != null) { + if (mPlayer.setVolume(volume)) { + currentVolume = volume; + } + } + } + + @Override + public void setPlaySpeed(float speed) { + if (mPlayer == null) { + return; + } + if (mStatu != PlayerStatu.IDEL) { + mPlayer.setPlaybackSpeed(speed); + } + } + + @Override + public double getVideoScale() { + return videoScale; + } + + @Override + public boolean isPlaying() { + if (mPlayer != null) { + return mPlayer.isNowPlaying(); + } + return false; + } + + @Override + public void rewindTo(int startMicrosecond) { + if (mPlayer == null) { + return; + } + if (mStatu != PlayerStatu.IDEL) { + for (StatuChangeListener callback : statuChangeCallbacks) { + mStatu = PlayerStatu.BUFFERING; + callback.statuCallback(PlayerStatu.BUFFERING); + } + mPlayer.rewindTo(startMicrosecond * MICRO_MILLI_RATE); + } + } + + /** + * Builder + * + * @since 2020-12-04 + */ + public static class Builder { + private Context mContext; + private String filePath; + private int startMillisecond; + private boolean isStretch; + private boolean isPause; + + /** + * constructor of Builder + * + * @param context context + */ + public Builder(Context context) { + mContext = context; + filePath = ""; + startMillisecond = 0; + } + + /** + * setFilePath of Builder + * + * @param filePath filePath + * @return builder + */ + public Builder setFilePath(String filePath) { + this.filePath = filePath; + return this; + } + + /** + * getFilePath of Builder + * + * @return filePath + */ + public String getFilePath() { + return filePath; + } + + /** + * setStartMillisecond of Builder + * + * @param startMillisecond startMillisecond + * @return builder + */ + public Builder setStartMillisecond(int startMillisecond) { + this.startMillisecond = startMillisecond; + return this; + } + + /** + * getStartMillisecond of Builder + * + * @return startMillisecond + */ + public int getStartMillisecond() { + return startMillisecond; + } + + /** + * setStretch of Builder + * + * @param isS isStretch + * @return Builder + */ + public Builder setStretch(boolean isS) { + this.isStretch = isS; + return this; + } + + /** + * setPause of Builder + * + * @param isP isPause + * @return Builder + */ + public Builder setPause(boolean isP) { + this.isPause = isP; + return this; + } + + /** + * create of Builder + * + * @return IPlayer + */ + public ImplPlayer create() { + return new HmPlayer(this); + } + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ImplLifecycle.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ImplLifecycle.java new file mode 100644 index 0000000000000000000000000000000000000000..e30c3aa983fb1be7ec5035b94a0c606cc3b81ac5 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ImplLifecycle.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.api; + +/** + * ImplLifecycle + * + * @since 2021-04-09 + * + */ +public interface ImplLifecycle { + /** + * onStart + * + */ + void onStart(); + + /** + * onForeground + * + */ + void onForeground(); + + /** + * onBackground + * + */ + void onBackground(); + + /** + * onStop + * + */ + void onStop(); +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ImplPlayModule.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ImplPlayModule.java new file mode 100644 index 0000000000000000000000000000000000000000..cfbeac7a223ce97483d4df28bc34fee3defc996a --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ImplPlayModule.java @@ -0,0 +1,37 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.api; + +/** + * IPlayModuler + * + * @since 2021-04-09 + * + */ +public interface ImplPlayModule { + /** + * bind + * + * @param player player + */ + void bind(ImplPlayer player); + + /** + * unbind + * + */ + void unbind(); +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ImplPlayer.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ImplPlayer.java new file mode 100644 index 0000000000000000000000000000000000000000..61cbaf48a89794889c99056a081377c8a0c523bf --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ImplPlayer.java @@ -0,0 +1,199 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.api; + +import ohos.agp.graphics.Surface; +import ohos.codelabs.distributedvideo.player.HmPlayer; +import ohos.codelabs.distributedvideo.player.constant.PlayerStatu; + +/** + * IPlayer interface + * + * @since 2021-04-04 + */ +public interface ImplPlayer { + /** + * addSurface + * + * @param surface surface + */ + void addSurface(Surface surface); + + /** + * addPlayerStatuCallback + * + * @param callback callback + */ + void addPlayerStatuCallback(StatuChangeListener callback); + + /** + * removePlayerStatuCallback + * + * @param callback callback + */ + void removePlayerStatuCallback(StatuChangeListener callback); + + /** + * addPlayerViewCallback + * + * @param callback callback + */ + void addPlayerViewCallback(ScreenChangeListener callback); + + /** + * removePlayerViewCallback + * + * @param callback callback + */ + void removePlayerViewCallback(ScreenChangeListener callback); + + /** + * play + */ + void play(); + + /** + * replay + */ + void replay(); + + /** + * reload + * + * @param filepath filepath + * @param startMillisecond startMillisecond + */ + void reload(String filepath, int startMillisecond); + + /** + * resume + */ + void resume(); + + /** + * pause + */ + void pause(); + + /** + * getCurrentPosition + * + * @return current position + */ + int getCurrentPosition(); + + /** + * getDuration + * + * @return duration + */ + int getDuration(); + + /** + * getVolume + * + * @return float + */ + float getVolume(); + + /** + * set play volume + * + * @param volume 0~1 + */ + void setVolume(float volume); + + /** + * set play speed + * + * @param speed 0~12 + */ + void setPlaySpeed(float speed); + + /** + * getVideoScale + * + * @return double + */ + double getVideoScale(); + + /** + * rewindTo + * + * @param startMicrosecond startMicrosecond(ms) + */ + void rewindTo(int startMicrosecond); + + /** + * isPlaying + * + * @return isPlaying + */ + boolean isPlaying(); + + /** + * stop + */ + void stop(); + + /** + * release + */ + void release(); + + /** + * getLifecycle + * + * @return ImplLifecycle + */ + ImplLifecycle getLifecycle(); + + /** + * getBuilder + * + * @return Builder + */ + HmPlayer.Builder getBuilder(); + + /** + * getPlayerStatu + * + * @return PlayerStatu + */ + PlayerStatu getPlayerStatu(); + + /** + * resizeScreen + * + * @param width width + * @param height height + */ + void resizeScreen(int width, int height); + + /** + * openGesture + * + * @param isOpen isOpen + */ + void openGesture(boolean isOpen); + + /** + * openGesture + * + * @return isGestureOpen + */ + boolean isGestureOpen(); +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ScreenChangeListener.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ScreenChangeListener.java new file mode 100644 index 0000000000000000000000000000000000000000..8118d987221af78d784e1fc2807458ec397a7ed2 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/ScreenChangeListener.java @@ -0,0 +1,32 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.api; + +/** + * ScreenChangeListener interface + * + * @since 2021-04-04 + * + */ +public interface ScreenChangeListener { + /** + * screenCallback + * + * @param width width + * @param height height + */ + void screenCallback(int width, int height); +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/StatuChangeListener.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/StatuChangeListener.java new file mode 100644 index 0000000000000000000000000000000000000000..3849273e6db25b0361a8a88b5ef3396996c2d58f --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/api/StatuChangeListener.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.api; + +import ohos.codelabs.distributedvideo.player.constant.PlayerStatu; + +/** + * StatuChangeListener interface + * + * @since 2021-04-04 + * + */ +public interface StatuChangeListener { + /** + * statuCallback + * + * @param statu statu + */ + void statuCallback(PlayerStatu statu); +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/Constants.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..75928c07721c8aceaa4803e317ce4579dfec21eb --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/Constants.java @@ -0,0 +1,119 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.constant; + +/** + * Constants + * + * @since 2021-04-04 + */ +public class Constants { + /** + * -1 + */ + public static final int NUMBER_NEGATIVE_1 = -1; + /** + * 2 + */ + public static final int NUMBER_2 = 2; + /** + * 2.0 + */ + public static final float NUMBER_FLOAT_2 = 2f; + /** + * 10 + */ + public static final int NUMBER_10 = 10; + /** + * 25 + */ + public static final int NUMBER_25 = 25; + /** + * 36 + */ + public static final int NUMBER_36 = 36; + /** + * 40 + */ + public static final int NUMBER_40 = 40; + /** + * 100 + */ + public static final int NUMBER_100 = 100; + /** + * 168 + */ + public static final int NUMBER_168 = 168; + /** + * 300 + */ + public static final int NUMBER_300 = 300; + /** + * 150 + */ + public static final int NUMBER_150 = 150; + /** + * 1000 + */ + public static final int NUMBER_1000 = 1000; + /** + * running + */ + public static final int PLAYER_PROGRESS_RUNNING = 0; + /** + * hide + */ + public static final int PLAYER_CONTROLLER_HIDE = 1; + /** + * hide + */ + public static final int PLAYER_CONTROLLER_SHOW = 2; + /** + * 100 + */ + public static final int ONE_HUNDRED_PERCENT = 100; + /** + * 100.0 + */ + public static final float ONE_HUNDRED_PERCENT_FLOAT = 100f; + /** + * rewind step + */ + public static final int REWIND_STEP = 5000; + /** + * volume step + */ + public static final float VOLUME_STEP = 0.1f; + /** + * INTENT STARTTIME PARAM + */ + public static final String INTENT_STARTTIME_PARAM = "intetn_starttime_param"; + /** + * INTENT PLAYURL PARAM + */ + public static final String INTENT_PLAYURL_PARAM = "intetn_playurl_param"; + /** + * INTENT PLAYSTATU PARAM + */ + public static final String INTENT_PLAYSTATU_PARAM = "intetn_playstatu_param"; + /** + * INTENT LANDSCREEN REQUEST CODE + */ + public static final int INTENT_LANDSCREEN_REQUEST_CODE = 1001; + + private Constants() { + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/ControlCode.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/ControlCode.java new file mode 100644 index 0000000000000000000000000000000000000000..9eccc7f4f6dd5eb4cbb67f55ce483d20a4aa3f73 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/ControlCode.java @@ -0,0 +1,88 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.constant; + +/** + * ControlCode enum + * + * @since 2020-12-04 + * + */ +public enum ControlCode { + /** + * resume to play the video when the video is paused + * + */ + RESUME(1001), + + /** + * pausethe video when the video is playing + * + */ + PAUSE(1002), + + /** + * pause the video when the video is playing + * + */ + STOP(1003), + + /** + * direct to the video + * + */ + SEEK(1004), + + /** + * forward the video-playing per second. + * + */ + FORWARD(1005), + + /** + * reduce the volume + * + */ + REWARD(1006), + + /** + * add the volume + * + */ + VOLUME_ADD(1007), + + /** + * reduce the volume + * + */ + VOLUME_REDUCED(1008), + + /** + * set volume + * + */ + VOLUME_SET(1009); + + private int code; + + ControlCode(int value) { + this.code = value; + } + + public int getCode() { + return code; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/GestureConst.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/GestureConst.java new file mode 100644 index 0000000000000000000000000000000000000000..a8a76db36fd7d82104a36b4f5b0a5611ad042916 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/GestureConst.java @@ -0,0 +1,172 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.constant; + +/** + * GestureConst + * + * @since 2021-04-04 + */ +public class GestureConst { + private static final int DEFAULT_LONG_PRESS_TIMEOUT = 500; + + private static final int TOUCH_SLOP = 64; + + private static final int TAP_TIMEOUT = 100; + + private static final int DOUBLE_TAP_TIMEOUT = 300; + + private static final int DOUBLE_TAP_MIN_TIME = 40; + + private static final int DOUBLE_TAP_SLOP = 100; + + private static final int MINIMUM_FLING_VELOCITY = 50; + + private static final int MAXIMUM_FLING_VELOCITY = 8000; + + private static final int DOUBLE_TAP_TOUCH_SLOP = TOUCH_SLOP; + + private static final float AMBIGUOUS_GESTURE_MULTIPLIER = 2f; + + private GestureConst() { + } + + /** + * getDoubleTapTimeout + * + * @return int + */ + public static int getDoubleTapTimeout() { + return DOUBLE_TAP_TIMEOUT; + } + + /** + * getDoubleTapMinTime + * + * @return int + */ + public static int getDoubleTapMinTime() { + return DOUBLE_TAP_MIN_TIME; + } + + /** + * getTouchSlop + * + * @return int + */ + public static int getTouchSlop() { + return TOUCH_SLOP; + } + + /** + * getLongPressTimeout + * + * @return int + */ + public static int getLongPressTimeout() { + return DEFAULT_LONG_PRESS_TIMEOUT; + } + + /** + * getTapTimeout + * + * @return int + */ + public static int getTapTimeout() { + return TAP_TIMEOUT; + } + + /** + * getDoubleTapSlop + * + * @return int + */ + public static int getDoubleTapSlop() { + return DOUBLE_TAP_SLOP; + } + + /** + * getMinimumFlingVelocity + * + * @return int + */ + public static int getMinimumFlingVelocity() { + return MINIMUM_FLING_VELOCITY; + } + + /** + * getMaximumFlingVelocity + * + * @return int + */ + public static int getMaximumFlingVelocity() { + return MAXIMUM_FLING_VELOCITY; + } + + /** + * getScaledTouchSlop + * + * @return int + */ + public static int getScaledTouchSlop() { + return TOUCH_SLOP; + } + + /** + * getScaledDoubleTapTouchSlop + * + * @return int + */ + public static int getScaledDoubleTapTouchSlop() { + return DOUBLE_TAP_TOUCH_SLOP; + } + + /** + * getScaledDoubleTapSlop + * + * @return int + */ + public static int getScaledDoubleTapSlop() { + return DOUBLE_TAP_SLOP; + } + + /** + * getScaledMinimumFlingVelocity + * + * @return int + */ + public static int getScaledMinimumFlingVelocity() { + return MINIMUM_FLING_VELOCITY; + } + + /** + * getScaledMaximumFlingVelocity + * + * @return int + */ + public static int getScaledMaximumFlingVelocity() { + return MAXIMUM_FLING_VELOCITY; + } + + /** + * getAmbiguousGestureMultiplier + * + * @return int + */ + public static float getAmbiguousGestureMultiplier() { + return AMBIGUOUS_GESTURE_MULTIPLIER; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/PlayerStatu.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/PlayerStatu.java new file mode 100644 index 0000000000000000000000000000000000000000..dcc05eeacdf255942cf9b47b765bba74d6b18144 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/constant/PlayerStatu.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.constant; + +/** + * PlayerStatu enum + * + * @since 2021-04-04 + * + */ +public enum PlayerStatu { + /** + * idel + * + */ + IDEL, + /** + * preparing + * + */ + PREPARING, + /** + * prepared + * + */ + PREPARED, + /** + * play + * + */ + PLAY, + /** + * pause + * + */ + PAUSE, + /** + * stop + * + */ + STOP, + /** + * complete + * + */ + COMPLETE, + /** + * error + * + */ + ERROR, + /** + * buffering + * + */ + BUFFERING +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/factory/SourceFactory.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/factory/SourceFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..46dc7cda09cd07ed01e507765c3561769c3eeb0d --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/factory/SourceFactory.java @@ -0,0 +1,86 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.factory; + +import ohos.app.Context; +import ohos.codelabs.distributedvideo.util.LogUtil; +import ohos.global.resource.RawFileDescriptor; +import ohos.media.common.Source; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.IOException; + +/** + * SourceFactory + * + * @since 2021-04-04 + * + */ +public class SourceFactory { + private static final String TAG = "SourceFactory"; + private static final String NET_HTTP_MATCH = "http"; + private static final String NET_RTMP_MATCH = "rtmp"; + private static final String NET_RTSP_MATCH = "rtsp"; + private static final String STORAGE_MATCH = "/storage/"; + + private Source mPlayerSource; + + /** + * constructor of SourceFactory + * + * @param context context + * @param path path + */ + public SourceFactory(Context context, String path) { + try { + initSourceType(context, path); + } catch (IOException e) { + LogUtil.error(TAG, "Audio resource is unavailable: "); + } + } + + private void initSourceType(Context context, String path) throws IOException { + if (context == null || path == null) { + return; + } + if (path.substring(0, NET_HTTP_MATCH.length()).equalsIgnoreCase(NET_HTTP_MATCH) + || path.substring(0, NET_RTMP_MATCH.length()).equalsIgnoreCase(NET_RTMP_MATCH) + || path.substring(0, NET_RTSP_MATCH.length()).equalsIgnoreCase(NET_RTSP_MATCH)) { + mPlayerSource = new Source(path); + } else if (path.startsWith(STORAGE_MATCH)) { + File file = new File(path); + if (file.exists()) { + FileInputStream fileInputStream = new FileInputStream(file); + FileDescriptor fileDescriptor = fileInputStream.getFD(); + mPlayerSource = new Source(fileDescriptor); + } + } else { + RawFileDescriptor fd = context.getResourceManager().getRawFileEntry(path).openRawFileDescriptor(); + mPlayerSource = new Source(fd.getFileDescriptor(), fd.getStartPosition(), fd.getFileSize()); + } + } + + /** + * getSource + * + * @return Source Source + */ + public Source getSource() { + return mPlayerSource; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/manager/GestureDetector.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/manager/GestureDetector.java new file mode 100644 index 0000000000000000000000000000000000000000..383dd0ff0fb40dac76c6e2a2962ef25d9bb28cd9 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/manager/GestureDetector.java @@ -0,0 +1,174 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.manager; + +import ohos.agp.components.VelocityDetector; +import ohos.codelabs.distributedvideo.player.constant.Constants; +import ohos.codelabs.distributedvideo.player.constant.GestureConst; +import ohos.multimodalinput.event.TouchEvent; + +/** + * GestureDetector + * + * @since 2021-04-09 + */ +public class GestureDetector { + /** + * MOVING_HORIZONTAL + */ + public static final int MOVING_HORIZONTAL = 0; + /** + * MOVING_VERTICAL + */ + public static final int MOVING_VERTICAL = 1; + private int currentMoveType; + + /** + * OnGestureListener + * + * @since 2021-04-09 + */ + public interface OnGestureListener { + /** + * 开始滚动时回调 + * + * @param windowX 手指移动时x位置 + * @param windowY 手指移动时y位置 + * @return is deliver + */ + boolean onTouchBegin(float windowX, float windowY); + + /** + * 发生滚动时回调 + * + * @param direction 移动方向 0:横向 1:纵向 + * @param windowX 手指移动时x位置 + * @param windowY 手指移动时y位置 + * @param distance 移动距离 + * @return is deliver + */ + boolean onTouchMoving(int direction, float windowX, float windowY, float distance); + + /** + * 结束滚动时回调 + * + * @param direction 移动方向 0:横向 1:纵向 + * @return is deliver + */ + boolean onTouchCancel(int direction); + } + + private final OnGestureListener mListener; + + private float mLastFocusX; + private float mLastFocusY; + private float mDownFocusX; + private float mDownFocusY; + + private VelocityDetector mVelocityTracker; + + /** + * GestureDetector + * + * @param listener listener + */ + public GestureDetector(OnGestureListener listener) { + mListener = listener; + } + + /** + * onTouchEvent + * + * @param ev ev + * @return boolean + */ + public boolean onTouchEvent(TouchEvent ev) { + final int action = ev.getAction(); + addVelocityDetector(ev); + float[] points = getFocusPoint(ev); + final float focusX = points[0]; + final float focusY = points[1]; + boolean isHandled = true; + switch (action) { + case TouchEvent.OTHER_POINT_DOWN: + case TouchEvent.PRIMARY_POINT_DOWN: + currentMoveType = Constants.NUMBER_NEGATIVE_1; + mDownFocusX = 0; + mDownFocusY = 0; + mListener.onTouchBegin(focusX, focusY); + break; + case TouchEvent.POINT_MOVE: + if (mDownFocusX == 0 || mDownFocusY == 0) { + mDownFocusX = focusX; + mDownFocusY = focusY; + mLastFocusX = focusX; + mLastFocusY = focusY; + } + final int deltaX = (int) (focusX - mDownFocusX); + final int deltaY = (int) (focusY - mDownFocusY); + int distanceX = Math.abs(deltaX); + int distanceY = Math.abs(deltaY); + if (distanceX > GestureConst.getScaledTouchSlop() || distanceY > GestureConst.getScaledTouchSlop()) { + if (distanceX >= distanceY) { + currentMoveType = MOVING_HORIZONTAL; + float scrollX = mLastFocusX - focusX; + isHandled = mListener.onTouchMoving(MOVING_HORIZONTAL, focusX, focusY, scrollX); + } else { + currentMoveType = MOVING_VERTICAL; + float scrollY = mLastFocusY - focusY; + isHandled = mListener.onTouchMoving(MOVING_VERTICAL, focusX, focusY, scrollY); + } + mLastFocusX = focusX; + mLastFocusY = focusY; + } + break; + case TouchEvent.PRIMARY_POINT_UP: + case TouchEvent.OTHER_POINT_UP: + case TouchEvent.CANCEL: + isHandled = mListener.onTouchCancel(currentMoveType); + break; + default: + break; + } + return isHandled; + } + + private void addVelocityDetector(TouchEvent ev) { + if (mVelocityTracker == null) { + mVelocityTracker = VelocityDetector.obtainInstance(); + } + mVelocityTracker.addEvent(ev); + } + + private float[] getFocusPoint(TouchEvent ev) { + final boolean isPointerUp = ev.getAction() == TouchEvent.OTHER_POINT_UP; + final int skipIndex = isPointerUp ? ev.getIndex() : Constants.NUMBER_NEGATIVE_1; + float sumX = 0; + float sumY = 0; + final int count = ev.getPointerCount(); + for (int i = 0; i < count; i++) { + if (skipIndex == i) { + continue; + } + sumX += ev.getPointerPosition(i).getX(); + sumY += ev.getPointerPosition(i).getY(); + } + final int div = isPointerUp ? count - 1 : count; + float focusX = sumX / div; + float focusY = sumY / div; + return new float[]{focusX, focusY}; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/manager/HmPlayerLifecycle.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/manager/HmPlayerLifecycle.java new file mode 100644 index 0000000000000000000000000000000000000000..fd886ac0ce1f7b95fbc76995661468c207de19df --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/manager/HmPlayerLifecycle.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.manager; + +import ohos.codelabs.distributedvideo.player.api.ImplLifecycle; +import ohos.codelabs.distributedvideo.player.api.ImplPlayer; +import ohos.codelabs.distributedvideo.player.constant.PlayerStatu; + +/** + * HmPlayerLifecycle + * + * @since 2021-04-09 + * + */ +public class HmPlayerLifecycle implements ImplLifecycle { + private static final String TAG = HmPlayerLifecycle.class.getSimpleName(); + private ImplPlayer mPlayer; + + /** + * HmPlayerLifecycle + * + * @param player player + */ + public HmPlayerLifecycle(ImplPlayer player) { + mPlayer = player; + } + + @Override + public void onStart() { + } + + @Override + public void onForeground() { + String url = mPlayer.getBuilder().getFilePath(); + int startMillisecond = mPlayer.getBuilder().getStartMillisecond(); + mPlayer.reload(url, startMillisecond); + } + + @Override + public void onBackground() { + mPlayer.getBuilder().setPause(mPlayer.getPlayerStatu() == PlayerStatu.PAUSE); + mPlayer.getBuilder().setStartMillisecond(mPlayer.getCurrentPosition()); + mPlayer.release(); + } + + @Override + public void onStop() { + mPlayer.release(); + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/util/CommonUtils.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/util/CommonUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..e1d57b2f8003a479e2702f91def012a01126b99e --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/util/CommonUtils.java @@ -0,0 +1,52 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.util; + +import ohos.app.Context; +import ohos.codelabs.distributedvideo.player.constant.Constants; +import ohos.codelabs.distributedvideo.util.LogUtil; +import ohos.global.resource.NotExistException; +import ohos.global.resource.WrongTypeException; + +import java.io.IOException; + +/** + * Common util + * + * @since 2021-04-04 + */ +public class CommonUtils { + private static final String TAG = CommonUtils.class.getSimpleName(); + + private CommonUtils() { + } + + /** + * 通过资源ID获取颜色 + * + * @param context comtext + * @param resourceId id + * @return int + */ + public static int getColor(Context context, int resourceId) { + try { + return context.getResourceManager().getElement(resourceId).getColor(); + } catch (IOException | NotExistException | WrongTypeException e) { + LogUtil.error(TAG, e.getMessage()); + } + return Constants.NUMBER_NEGATIVE_1; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/util/DateUtils.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/util/DateUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..e532e199e56c99d4644ec16ee3afb8bab5d16429 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/util/DateUtils.java @@ -0,0 +1,63 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.util; + +import java.util.Locale; + +/** + * Date util + * + * @since 2021-04-04 + */ +public class DateUtils { + private static final int ONE_SECONDS_MS = 1000; + private static final int ONE_MINS_MINUTES = 60; + private static final int NUMBER = 16; + private static final String TIME_FORMAT = "%02d"; + private static final String SEMICOLON = ":"; + + private DateUtils() { + } + + /** + * conversion of msToString + * + * @param ms ms + * @return string + */ + public static String msToString(int ms) { + StringBuilder sb = new StringBuilder(NUMBER); + int seconds = ms / ONE_SECONDS_MS; + int minutes = seconds / ONE_MINS_MINUTES; + if (minutes > ONE_MINS_MINUTES) { + sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, minutes / ONE_MINS_MINUTES)); + sb.append(SEMICOLON); + sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, minutes % ONE_MINS_MINUTES)); + sb.append(SEMICOLON); + } else { + sb.append("00:"); + sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, minutes)); + sb.append(SEMICOLON); + } + + if (seconds > minutes * ONE_MINS_MINUTES) { + sb.append(String.format(Locale.ENGLISH, TIME_FORMAT, seconds - minutes * ONE_MINS_MINUTES)); + } else { + sb.append("00"); + } + return sb.toString(); + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/PlayerGestureView.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/PlayerGestureView.java new file mode 100644 index 0000000000000000000000000000000000000000..11999e2a99221db72061191a8f23a1956cdc8a5b --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/PlayerGestureView.java @@ -0,0 +1,203 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.view; + +import ohos.agp.colors.RgbColor; +import ohos.agp.components.AttrSet; +import ohos.agp.components.DirectionalLayout; +import ohos.agp.components.Image; +import ohos.agp.components.Text; +import ohos.agp.components.element.ShapeElement; +import ohos.agp.utils.Color; +import ohos.agp.utils.LayoutAlignment; +import ohos.app.Context; +import ohos.codelabs.distributedvideo.ResourceTable; +import ohos.codelabs.distributedvideo.player.api.ImplPlayModule; +import ohos.codelabs.distributedvideo.player.api.ImplPlayer; +import ohos.codelabs.distributedvideo.player.constant.Constants; +import ohos.codelabs.distributedvideo.player.constant.PlayerStatu; +import ohos.codelabs.distributedvideo.player.manager.GestureDetector; +import ohos.codelabs.distributedvideo.player.util.CommonUtils; +import ohos.codelabs.distributedvideo.player.util.DateUtils; + +/** + * PlayerGestureView + * + * @since 2021-04-04 + */ +public class PlayerGestureView extends DirectionalLayout implements ImplPlayModule, GestureDetector.OnGestureListener { + private static final int MOVING_TYPE_INIT = -1; + private static final int VOLUME_TYPE = 0; + private static final int PROGRESS_DOWN_TYPE = 1; + private static final int PROGRESS_UP_TYPE = 2; + private static final int LIGHT_BRIGHT_TYPE = 3; + private ImplPlayer player; + private int currentPercent; + private int currentMoveType; + private int beginPosition; + + private Image gestureImage; + private Text gestureText; + + /** + * constructor of PlayerGestureView + * + * @param context context + */ + public PlayerGestureView(Context context) { + this(context, null); + } + + /** + * constructor of PlayerGestureView + * + * @param context context + * @param attrSet attSet + */ + public PlayerGestureView(Context context, AttrSet attrSet) { + this(context, attrSet, null); + } + + /** + * constructor of PlayerGestureView + * + * @param context context + * @param attrSet attSet + * @param styleName styleName + */ + public PlayerGestureView(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); + initView(); + hide(); + } + + private void initView() { + ShapeElement shapeElement = new ShapeElement(); + shapeElement.setRgbColor( + RgbColor.fromArgbInt(CommonUtils.getColor(mContext, ResourceTable.Color_half_transparent))); + shapeElement.setCornerRadius(Constants.NUMBER_25); + setOrientation(DirectionalLayout.VERTICAL); + setAlignment(LayoutAlignment.HORIZONTAL_CENTER); + setBackground(shapeElement); + gestureImage = new Image(mContext); + gestureImage.setWidth(Constants.NUMBER_150); + gestureImage.setHeight(Constants.NUMBER_150); + gestureImage.setScaleMode(Image.ScaleMode.STRETCH); + gestureImage.setMarginsTopAndBottom(Constants.NUMBER_40, Constants.NUMBER_10); + gestureText = new Text(mContext); + gestureText.setTextSize(Constants.NUMBER_36); + gestureText.setTextColor(new Color(CommonUtils.getColor(mContext, ResourceTable.Color_white))); + gestureText.setMarginsTopAndBottom(Constants.NUMBER_10, Constants.NUMBER_40); + addComponent(gestureImage); + addComponent(gestureText); + } + + private void show(int type, String content) { + int gestureImg = ResourceTable.Media_ic_horns; + switch (type) { + case VOLUME_TYPE: + gestureImg = ResourceTable.Media_ic_horns; + break; + case PROGRESS_DOWN_TYPE: + gestureImg = ResourceTable.Media_ic_backward; + break; + case PROGRESS_UP_TYPE: + gestureImg = ResourceTable.Media_ic_forward; + break; + case LIGHT_BRIGHT_TYPE: + gestureImg = ResourceTable.Media_ic_bright; + break; + default: + break; + } + gestureImage.setPixelMap(gestureImg); + gestureText.setText(content); + if (getVisibility() != VISIBLE) { + setVisibility(VISIBLE); + } + } + + private void hide() { + if (getVisibility() == VISIBLE) { + setVisibility(HIDE); + } + } + + @Override + public void bind(ImplPlayer implPlayer) { + this.player = implPlayer; + this.player.addPlayerStatuCallback(statu -> { + mContext.getUITaskDispatcher().asyncDispatch(() -> { + if (statu == PlayerStatu.STOP || statu == PlayerStatu.COMPLETE) { + hide(); + } + }); + }); + } + + @Override + public void unbind() { + } + + @Override + public boolean onTouchBegin(float focusX, float focusY) { + if (player != null) { + currentPercent = 0; + currentMoveType = MOVING_TYPE_INIT; + beginPosition = player.getCurrentPosition(); + } + return true; + } + + @Override + public boolean onTouchMoving(int direction, float focusX, float focusY, float distance) { + if (currentMoveType == MOVING_TYPE_INIT) { + currentMoveType = direction; + } + if (currentMoveType == direction && player != null) { + if (currentMoveType == GestureDetector.MOVING_HORIZONTAL) { + currentPercent += distance < 0 ? Constants.NUMBER_1000 : -Constants.NUMBER_1000; + int type = currentPercent < 0 + ? PlayerGestureView.PROGRESS_DOWN_TYPE : PlayerGestureView.PROGRESS_UP_TYPE; + int value = Math.abs(currentPercent); + String content = (currentPercent < 0 ? "- " : "+ ") + DateUtils.msToString(value); + show(type, content); + } else if (currentMoveType == GestureDetector.MOVING_VERTICAL) { + int interval = getHeight() / Constants.NUMBER_2; + if (focusX <= getWidth() / Constants.NUMBER_FLOAT_2) { + show(PlayerGestureView.LIGHT_BRIGHT_TYPE, "100%"); + } else { + float volume = player.getVolume() + distance / interval; + volume = (volume < 0) ? 0 : Math.min(volume, 1); + show(PlayerGestureView.VOLUME_TYPE, (int) (volume * Constants.NUMBER_100) + "%"); + player.setVolume(volume); + } + } else { + return false; + } + } + return true; + } + + @Override + public boolean onTouchCancel(int direction) { + if (currentMoveType == GestureDetector.MOVING_HORIZONTAL && player != null) { + player.rewindTo(beginPosition + currentPercent); + } + hide(); + return true; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/PlayerLoading.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/PlayerLoading.java new file mode 100644 index 0000000000000000000000000000000000000000..b3b7d6a5c338397725590ff606f87403dfa06370 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/PlayerLoading.java @@ -0,0 +1,148 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.view; + +import ohos.agp.animation.AnimatorProperty; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.components.Component.TouchEventListener; +import ohos.agp.components.ComponentContainer; +import ohos.agp.components.Image; +import ohos.agp.components.LayoutScatter; +import ohos.app.Context; +import ohos.codelabs.distributedvideo.ResourceTable; +import ohos.codelabs.distributedvideo.player.api.ImplPlayModule; +import ohos.codelabs.distributedvideo.player.api.ImplPlayer; +import ohos.multimodalinput.event.TouchEvent; + +/** + * PlayerLoading + * + * @since 2021-04-04 + */ +public class PlayerLoading extends ComponentContainer implements ImplPlayModule, TouchEventListener { + private static final int HALF_NUMBER = 2; + private static final int ANIM_ROTATE = 360; + private static final int ANIM_DURATION = 2000; + private static final int ANIM_LOOPED_COUNT = -1; + private ImplPlayer mPlayer; + private Image mLoading; + private AnimatorProperty mLoadingAnim; + + /** + * constructor of PlayerLoading + * + * @param context context + */ + public PlayerLoading(Context context) { + this(context, null); + } + + /** + * constructor of PlayerLoading + * + * @param context context + * @param attrSet attSet + */ + public PlayerLoading(Context context, AttrSet attrSet) { + this(context, attrSet, null); + } + + /** + * constructor of PlayerLoading + * + * @param context context + * @param attrSet attSet + * @param styleName styleName + */ + public PlayerLoading(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); + initView(context); + } + + private void initView(Context context) { + Component loadingContainer = + LayoutScatter.getInstance(context).parse(ResourceTable.Layout_player_loading_layout, null, false); + if (loadingContainer.findComponentById(ResourceTable.Id_image_loading) instanceof Image) { + mLoading = (Image) loadingContainer.findComponentById(ResourceTable.Id_image_loading); + initAnim(); + } + addComponent(loadingContainer); + hide(); + setTouchEventListener(this); + } + + private void initAnim() { + int with = mLoading.getWidth() / HALF_NUMBER; + int height = mLoading.getHeight() / HALF_NUMBER; + mLoading.setPivotX(with); + mLoading.setPivotY(height); + mLoadingAnim = mLoading.createAnimatorProperty(); + mLoadingAnim.rotate(ANIM_ROTATE).setDuration(ANIM_DURATION).setLoopedCount(ANIM_LOOPED_COUNT); + } + + private void initListener() { + mPlayer.addPlayerStatuCallback(statu -> mContext.getUITaskDispatcher().asyncDispatch(() -> { + switch (statu) { + case PREPARING: + case BUFFERING: + show(); + break; + case PLAY: + hide(); + break; + default: + break; + } + })); + } + + /** + * show of PlayerLoading + */ + public void show() { + if (mLoadingAnim.isPaused()) { + mLoadingAnim.resume(); + } else { + mLoadingAnim.start(); + } + setVisibility(VISIBLE); + } + + /** + * hide of PlayerLoading + */ + public void hide() { + setVisibility(INVISIBLE); + mLoadingAnim.pause(); + } + + @Override + public void bind(ImplPlayer player) { + mPlayer = player; + initListener(); + } + + @Override + public void unbind() { + mLoadingAnim.release(); + } + + @Override + public boolean onTouchEvent(Component component, TouchEvent touchEvent) { + return true; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/PlayerView.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/PlayerView.java new file mode 100644 index 0000000000000000000000000000000000000000..3861f3a5f4ed9d06958da9fe972251b4bc4f5709 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/PlayerView.java @@ -0,0 +1,179 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.view; + +import ohos.agp.components.Attr; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.components.Component.LayoutRefreshedListener; +import ohos.agp.components.ComponentContainer; +import ohos.agp.components.DependentLayout; +import ohos.agp.components.surfaceprovider.SurfaceProvider; +import ohos.agp.graphics.Surface; +import ohos.agp.graphics.SurfaceOps; +import ohos.agp.window.service.WindowManager; +import ohos.app.Context; +import ohos.codelabs.distributedvideo.player.api.ImplPlayModule; +import ohos.codelabs.distributedvideo.player.api.ImplPlayer; +import ohos.codelabs.distributedvideo.player.constant.Constants; +import ohos.codelabs.distributedvideo.player.manager.GestureDetector; + +import java.util.Optional; + +/** + * PlayerView + * + * @since 2021-04-04 + */ +public class PlayerView extends DependentLayout implements ImplPlayModule, LayoutRefreshedListener { + private ImplPlayer player; + private SurfaceProvider surfaceView; + private Surface surface; + private PlayerGestureView gestureView; + private GestureDetector gestureDetector; + private boolean isTopPlay; + private int viewWidth; + private int viewHeight; + + /** + * constructor of PlayerView + * + * @param context context + */ + public PlayerView(Context context) { + this(context, null); + } + + /** + * constructor of PlayerView + * + * @param context context + * @param attrSet attSet + */ + public PlayerView(Context context, AttrSet attrSet) { + this(context, attrSet, null); + } + + /** + * constructor of PlayerView + * + * @param context context + * @param attrSet attSet + * @param styleName styleName + */ + public PlayerView(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); + WindowManager.getInstance().getTopWindow().get().setTransparent(true); // 不设置窗体透明会挡住播放内容,除非设置pinToZTop为true + if (attrSet != null) { + Optional optIsTopPlay = attrSet.getAttr("top_play"); + optIsTopPlay.ifPresent(attr -> isTopPlay = "true".equals(attr.getStringValue())); + } + initView(); + initListener(); + setLayoutRefreshedListener(this); + } + + private void initView() { + surfaceView = new SurfaceProvider(mContext); + LayoutConfig layoutConfig = new LayoutConfig(); + layoutConfig.addRule(LayoutConfig.CENTER_IN_PARENT); + surfaceView.setLayoutConfig(layoutConfig); + surfaceView.pinToZTop(isTopPlay); + addComponent(surfaceView); + addGestureView(); + } + + private void addGestureView() { + gestureView = new PlayerGestureView(mContext); + LayoutConfig config = + new LayoutConfig(Constants.NUMBER_300, ComponentContainer.LayoutConfig.MATCH_CONTENT); + config.addRule(LayoutConfig.CENTER_IN_PARENT); + gestureView.setLayoutConfig(config); + addComponent(gestureView); + } + + private void initListener() { + gestureDetector = new GestureDetector(gestureView); + surfaceView.setTouchEventListener((component, touchEvent) -> + canGesture() && gestureDetector.onTouchEvent(touchEvent)); + surfaceView.getSurfaceOps().ifPresent(surfaceOps -> surfaceOps.addCallback(new SurfaceOps.Callback() { + @Override + public void surfaceCreated(SurfaceOps surfaceOps) { + surface = surfaceOps.getSurface(); + if (player != null) { + player.addSurface(surface); + } + } + + @Override + public void surfaceChanged(SurfaceOps surfaceOps, int info, int width, int height) { + } + + @Override + public void surfaceDestroyed(SurfaceOps surfaceOps) { + } + })); + } + + private boolean canGesture() { + return gestureDetector != null + && player != null + && player.isGestureOpen(); + } + + private void updateVideoSize(double videoScale) { + if (videoScale > 1) { + surfaceView.setWidth(viewWidth); + surfaceView.setHeight((int) Math.min(viewWidth / videoScale, viewHeight)); + } else { + surfaceView.setHeight(viewHeight); + surfaceView.setWidth((int) Math.min(viewHeight * videoScale, viewWidth)); + } + } + + @Override + public void bind(ImplPlayer implPlayer) { + this.player = implPlayer; + gestureView.bind(player); + this.player.addPlayerViewCallback((width, height) -> mContext.getUITaskDispatcher().asyncDispatch(() -> { + if (width > 0) { + setWidth(width); + } + if (height > 0) { + setHeight(height); + } + })); + } + + @Override + public void unbind() { + surfaceView.removeFromWindow(); + surfaceView = null; + surface = null; + } + + @Override + public void onRefreshed(Component component) { + int newWidth = component.getWidth(); + int newHeight = component.getHeight(); + double videoScale = player.getVideoScale(); + if (videoScale != Constants.NUMBER_NEGATIVE_1 && (newWidth != viewWidth || newHeight != viewHeight)) { + viewWidth = newWidth; + viewHeight = newHeight; + mContext.getUITaskDispatcher().asyncDispatch(() -> updateVideoSize(videoScale)); + } + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/SimplePlayerController.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/SimplePlayerController.java new file mode 100644 index 0000000000000000000000000000000000000000..a71fccd6b7ab0b806b62b5103c2b5c2b58e2b212 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/player/view/SimplePlayerController.java @@ -0,0 +1,306 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.player.view; + +import ohos.agp.colors.RgbColor; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.components.ComponentContainer; +import ohos.agp.components.DirectionalLayout; +import ohos.agp.components.Image; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.Slider; +import ohos.agp.components.Text; +import ohos.agp.components.element.ShapeElement; +import ohos.app.Context; +import ohos.codelabs.distributedvideo.ResourceTable; +import ohos.codelabs.distributedvideo.player.api.ImplPlayModule; +import ohos.codelabs.distributedvideo.player.api.ImplPlayer; +import ohos.codelabs.distributedvideo.player.api.StatuChangeListener; +import ohos.codelabs.distributedvideo.player.constant.Constants; +import ohos.codelabs.distributedvideo.player.constant.PlayerStatu; +import ohos.codelabs.distributedvideo.player.util.DateUtils; +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.eventhandler.InnerEvent; + +/** + * PlayerController + * + * @since 2021-04-04 + */ +public class SimplePlayerController extends ComponentContainer implements ImplPlayModule { + private static final int THUMB_RED = 255; + private static final int THUMB_GREEN = 255; + private static final int THUMB_BLUE = 240; + private static final int THUMB_WIDTH = 40; + private static final int THUMB_HEIGHT = 40; + private static final int THUMB_RADIUS = 20; + private static final int CONTROLLER_HIDE_DLEY_TIME = 5000; + private static final int PROGRESS_RUNNING_TIME = 1000; + private boolean mIsDragMode = false; + private Context mContext; + private ImplPlayer mPlayer; + private DirectionalLayout bottomLayout; + private Image mPlayToogle; + private Image mForward; + private Image mBackward; + private Slider mProgressBar; + private Text mCurrentTime; + private Text mTotleTime; + private ControllerHandler mHandler; + private StatuChangeListener mStatuChangeListener = new StatuChangeListener() { + @Override + public void statuCallback(PlayerStatu statu) { + mContext.getUITaskDispatcher().asyncDispatch(() -> { + switch (statu) { + case PREPARING: + mPlayToogle.setClickable(false); + mProgressBar.setEnabled(false); + mProgressBar.setProgressValue(0); + break; + case PREPARED: + mProgressBar.setMaxValue(mPlayer.getDuration()); + mTotleTime.setText(DateUtils.msToString(mPlayer.getDuration())); + break; + case PLAY: + showController(false); + mPlayToogle.setPixelMap(ResourceTable.Media_ic_music_stop); + mPlayToogle.setClickable(true); + mProgressBar.setEnabled(true); + break; + case PAUSE: + mPlayToogle.setPixelMap(ResourceTable.Media_ic_music_play); + break; + case STOP: + case COMPLETE: + mPlayToogle.setPixelMap(ResourceTable.Media_ic_update); + mProgressBar.setEnabled(false); + break; + default: + break; + } + }); + } + }; + + /** + * constructor of SimplePlayerController + * + * @param context context + */ + public SimplePlayerController(Context context) { + this(context, null); + } + + /** + * constructor of SimplePlayerController + * + * @param context context + * @param attrSet attSet + */ + public SimplePlayerController(Context context, AttrSet attrSet) { + this(context, attrSet, null); + } + + /** + * constructor of SimplePlayerController + * + * @param context context + * @param attrSet attSet + * @param styleName styleName + */ + public SimplePlayerController(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); + mContext = context; + createHandler(); + initView(); + initListener(); + } + + private void createHandler() { + EventRunner runner = EventRunner.create(true); + if (runner == null) { + return; + } + mHandler = new ControllerHandler(runner); + } + + private void initView() { + Component playerController = + LayoutScatter.getInstance(mContext) + .parse(ResourceTable.Layout_simple_player_controller_layout, null, false); + addComponent(playerController); + if (playerController.findComponentById(ResourceTable.Id_controller_bottom_layout) + instanceof DirectionalLayout) { + bottomLayout = (DirectionalLayout) playerController + .findComponentById(ResourceTable.Id_controller_bottom_layout); + } + if (playerController.findComponentById(ResourceTable.Id_play_controller) instanceof Image) { + mPlayToogle = (Image) playerController.findComponentById(ResourceTable.Id_play_controller); + } + if (playerController.findComponentById(ResourceTable.Id_play_forward) instanceof Image) { + mForward = (Image) playerController.findComponentById(ResourceTable.Id_play_forward); + } + if (playerController.findComponentById(ResourceTable.Id_play_backward) instanceof Image) { + mBackward = (Image) playerController.findComponentById(ResourceTable.Id_play_backward); + } + if (playerController.findComponentById(ResourceTable.Id_progress) instanceof Slider) { + mProgressBar = (Slider) playerController.findComponentById(ResourceTable.Id_progress); + } + ShapeElement shapeElement = new ShapeElement(); + shapeElement.setRgbColor(new RgbColor(THUMB_RED, THUMB_GREEN, THUMB_BLUE)); + shapeElement.setBounds(0, 0, THUMB_WIDTH, THUMB_HEIGHT); + shapeElement.setCornerRadius(THUMB_RADIUS); + mProgressBar.setThumbElement(shapeElement); + if (playerController.findComponentById(ResourceTable.Id_current_time) instanceof Text) { + mCurrentTime = (Text) playerController.findComponentById(ResourceTable.Id_current_time); + } + if (playerController.findComponentById(ResourceTable.Id_end_time) instanceof Text) { + mTotleTime = (Text) playerController.findComponentById(ResourceTable.Id_end_time); + } + } + + private void initListener() { + bottomLayout.setTouchEventListener((component, touchEvent) -> true); + } + + private void initPlayListener() { + mPlayer.addPlayerStatuCallback(mStatuChangeListener); + mPlayToogle.setClickedListener(component -> { + if (mPlayer.isPlaying()) { + mPlayer.pause(); + } else { + if (mPlayer.getPlayerStatu() == PlayerStatu.STOP) { + mPlayer.replay(); + } else { + mPlayer.resume(); + } + } + }); + mForward.setClickedListener(component -> + mPlayer.rewindTo(mPlayer.getCurrentPosition() + Constants.REWIND_STEP)); + mBackward.setClickedListener(component -> + mPlayer.rewindTo(mPlayer.getCurrentPosition() - Constants.REWIND_STEP)); + mProgressBar.setValueChangedListener( + new Slider.ValueChangedListener() { + @Override + public void onProgressUpdated(Slider slider, int value, boolean isB) { + mContext.getUITaskDispatcher().asyncDispatch(() -> + mCurrentTime.setText(DateUtils.msToString(value))); + } + + @Override + public void onTouchStart(Slider slider) { + mIsDragMode = true; + mHandler.removeEvent(Constants.PLAYER_PROGRESS_RUNNING, EventHandler.Priority.IMMEDIATE); + } + + @Override + public void onTouchEnd(Slider slider) { + mIsDragMode = false; + if (slider.getProgress() == mPlayer.getDuration()) { + mPlayer.stop(); + } else { + mPlayer.rewindTo(slider.getProgress()); + } + } + }); + } + + /** + * showController of PlayerController + * + * @param isAutoHide isAutoHide + */ + public void showController(boolean isAutoHide) { + mHandler.sendEvent(Constants.PLAYER_CONTROLLER_SHOW, EventHandler.Priority.HIGH); + if (isAutoHide) { + hideController(CONTROLLER_HIDE_DLEY_TIME); + } else { + mHandler.removeEvent(Constants.PLAYER_CONTROLLER_HIDE); + } + } + + /** + * hideController of PlayerController + * + * @param delay delay + */ + public void hideController(int delay) { + mHandler.removeEvent(Constants.PLAYER_CONTROLLER_HIDE); + mHandler.sendEvent(Constants.PLAYER_CONTROLLER_HIDE, delay, EventHandler.Priority.HIGH); + } + + @Override + public void bind(ImplPlayer player) { + mPlayer = player; + initPlayListener(); + } + + @Override + public void unbind() { + mHandler.removeAllEvent(); + mHandler = null; + } + + /** + * ControllerHandler + * + * @author chenweiquan + * @since 2020-12-04 + */ + private class ControllerHandler extends EventHandler { + private ControllerHandler(EventRunner runner) { + super(runner); + } + + @Override + public void processEvent(InnerEvent event) { + super.processEvent(event); + if (event == null) { + return; + } + switch (event.eventId) { + case Constants.PLAYER_PROGRESS_RUNNING: + if (mPlayer != null && mPlayer.isPlaying() && !mIsDragMode) { + mContext.getUITaskDispatcher().asyncDispatch(() -> { + mProgressBar.setProgressValue(mPlayer.getCurrentPosition()); + mCurrentTime.setText(DateUtils.msToString(mPlayer.getCurrentPosition())); + }); + mHandler.sendEvent( + Constants.PLAYER_PROGRESS_RUNNING, PROGRESS_RUNNING_TIME, Priority.IMMEDIATE); + } + break; + case Constants.PLAYER_CONTROLLER_HIDE: + mContext.getUITaskDispatcher().asyncDispatch(() -> setVisibility(INVISIBLE)); + mHandler.removeEvent(Constants.PLAYER_PROGRESS_RUNNING); + break; + case Constants.PLAYER_CONTROLLER_SHOW: + mHandler.removeEvent(Constants.PLAYER_PROGRESS_RUNNING); + mHandler.sendEvent(Constants.PLAYER_PROGRESS_RUNNING, Priority.IMMEDIATE); + mContext.getUITaskDispatcher().asyncDispatch(() -> { + if (getVisibility() != VISIBLE) { + setVisibility(VISIBLE); + } + }); + break; + default: + break; + } + } + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/provider/AdvertisementProvider.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/provider/AdvertisementProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..bc80c017d251206991973aa9887f434201b1bea5 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/provider/AdvertisementProvider.java @@ -0,0 +1,66 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.provider; + +import ohos.agp.components.Component; +import ohos.agp.components.ComponentContainer; +import ohos.agp.components.PageSliderProvider; + +import java.util.List; + +/** + * Advertising display adapter + * + * @param type + * @since 2020-12-04 + */ +public class AdvertisementProvider extends PageSliderProvider { + private List componentList; + + /** + * constructor + * + * @param componentList component list + */ + public AdvertisementProvider(List componentList) { + this.componentList = componentList; + } + + /** + * get count + * + * @return int + */ + public int getCount() { + return componentList.size(); + } + + @Override + public Object createPageInContainer(ComponentContainer componentContainer, int index) { + componentContainer.addComponent(componentList.get(index)); + return componentList.get(index); + } + + @Override + public void destroyPageFromContainer(ComponentContainer componentContainer, int index, Object obj) { + componentContainer.removeComponent(componentList.get(index)); + } + + @Override + public boolean isPageMatchToObject(Component component, Object obj) { + return component == obj; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/provider/CommonProvider.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/provider/CommonProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..2c5270edebfa590b6fe9f65ba772a0b72429c5bd --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/provider/CommonProvider.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.provider; + +import ohos.agp.components.BaseItemProvider; +import ohos.agp.components.Component; +import ohos.agp.components.ComponentContainer; +import ohos.app.Context; + +import java.util.ArrayList; +import java.util.List; + +/** + * CommonAdapter + * + * @param type + * @since 2020-12-04 + */ +public abstract class CommonProvider extends BaseItemProvider { + /** + * source list + */ + protected List datas; + /** + * context + */ + protected Context context; + /** + * the resource id + */ + protected int layoutId; + + /** + * constructor of CommonAdapter + * + * @param context context + * @param layoutId id + */ + public CommonProvider(Context context, final int layoutId) { + this(new ArrayList(0), context, layoutId); + } + + /** + * constructor of CommonAdapter + * + * @param context context + * @param layoutId id + * @param datas listContainer data + */ + public CommonProvider(List datas, Context context, int layoutId) { + this.datas = datas; + this.context = context; + this.layoutId = layoutId; + } + + @Override + public int getCount() { + return datas != null ? datas.size() : 0; + } + + /** + * return data + * + * @param position position + * @return data + */ + @Override + public T getItem(int position) { + return datas.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public Component getComponent(int position, Component component, ComponentContainer parent) { + ViewProvider holder = ViewProvider.get(context, component, parent, layoutId, position); + + convert(holder, getItem(position), position); + return holder.getComponentView(); + } + + /** + * convert to a new Collection,contains clear it + * + * @param holder holder + * @param item item + * @param position position + */ + protected abstract void convert(ViewProvider holder, T item, int position); +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/provider/ViewProvider.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/provider/ViewProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..19a04a7dba79cfde66183c5218da0d92e4aaaffe --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/provider/ViewProvider.java @@ -0,0 +1,194 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.provider; + +import ohos.agp.components.Component; +import ohos.agp.components.ComponentContainer; +import ohos.agp.components.Image; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.Text; +import ohos.app.Context; + +import java.util.HashMap; + +/** + * ViewProvider + * + * @since 2020-12-04 + * + */ +public class ViewProvider { + /** + * set Position + */ + protected int componentPosition; + /** + * set layout id + */ + protected int layoutId; + private Component component; + private Context context; + private HashMap views; + + /** + * constructor of ViewProvider + * + * @param context context + * @param itemView itemView + * @param parent parent + * @param position position + */ + public ViewProvider(Context context, Component itemView, ComponentContainer parent, int position) { + this.context = context; + component = itemView; + this.componentPosition = position; + views = new HashMap(0); + component.setTag(this); + } + + /** + * constructor of ViewProvider + * + * @param context context + * @param convertView convertView + * @param parent parent + * @param layoutId layoutId + * @param position position + * @return ViewProvider + */ + public static ViewProvider get(Context context, Component convertView, ComponentContainer parent, + int layoutId, int position) { + if (convertView == null) { + Component itemView = LayoutScatter.getInstance(context).parse(layoutId, null, false); + ViewProvider viewProvider = new ViewProvider(context, itemView, parent, position); + viewProvider.layoutId = layoutId; + return viewProvider; + } else { + ViewProvider viewProvider = null; + Object object = convertView.getTag(); + if (object instanceof ViewProvider) { + viewProvider = (ViewProvider) object; + viewProvider.componentPosition = position; + } + return viewProvider; + } + } + + /** + * Get the control by viewId + * + * @param viewId viewId + * @param generic + * @return view + */ + public T getView(int viewId) { + Component view = views.get(viewId); + if (view == null) { + view = component.findComponentById(viewId); + views.put(viewId, view); + } + return (T) view; + } + + /** + * return Component + * + * @return Component + */ + public Component getComponentView() { + return component; + } + + /** + * get layout id + * + * @return xmlId + */ + public int getLayoutId() { + return layoutId; + } + + /** + * update pointer + * + * @param position position + */ + public void updatePosition(int position) { + this.componentPosition = position; + } + + /** + * get item position + * + * @return int + */ + public int getItemPosition() { + return componentPosition; + } + + /** + * set text + * + * @param viewId viewId + * @param text text + * @return ViewProvider + */ + public ViewProvider setText(int viewId, String text) { + Text tv = getView(viewId); + tv.setText(text); + return this; + } + + /** + * set image + * + * @param viewId viewId + * @param resId ImageResource + * @return ViewProvider + */ + public ViewProvider setImageResource(int viewId, int resId) { + Image image = getView(viewId); + image.setPixelMap(resId); + image.setScaleMode(Image.ScaleMode.STRETCH); + return this; + } + + /** + * set onClick Listener + * + * @param viewId viewId + * @param listener listener + * @return ViewProvider + */ + public ViewProvider setOnClickListener(int viewId, Component.ClickedListener listener) { + Component newComponent = getView(viewId); + newComponent.setClickedListener(listener); + return this; + } + + /** + * set OnTouch Listener + * + * @param viewId viewId + * @param listener listener + * @return ViewProvider + */ + public ViewProvider setOnTouchListener(int viewId, Component.TouchEventListener listener) { + Component newComponent = getView(viewId); + newComponent.setTouchEventListener(listener); + return this; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/slice/MainAbilitySlice.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/slice/MainAbilitySlice.java new file mode 100644 index 0000000000000000000000000000000000000000..fa012c5667e69846525fd87ac3c83a77bfb0856d --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/slice/MainAbilitySlice.java @@ -0,0 +1,223 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.slice; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.aafwk.content.Operation; +import ohos.agp.colors.RgbColor; +import ohos.agp.components.Component; +import ohos.agp.components.Image; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.ListContainer; +import ohos.agp.components.PageSlider; +import ohos.agp.components.PageSliderIndicator; +import ohos.agp.components.Text; +import ohos.agp.components.element.ShapeElement; +import ohos.agp.text.Font; +import ohos.agp.utils.Color; +import ohos.codelabs.distributedvideo.MainAbility; +import ohos.codelabs.distributedvideo.PlayerAbility; +import ohos.codelabs.distributedvideo.ResourceTable; +import ohos.codelabs.distributedvideo.data.AdvertisementMo; +import ohos.codelabs.distributedvideo.data.VideoListMo; +import ohos.codelabs.distributedvideo.data.VideoTabStyle; +import ohos.codelabs.distributedvideo.provider.AdvertisementProvider; +import ohos.codelabs.distributedvideo.provider.CommonProvider; +import ohos.codelabs.distributedvideo.provider.ViewProvider; +import ohos.codelabs.distributedvideo.util.LogUtil; +import ohos.codelabs.distributedvideo.util.MediaUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * the main page + * + * @since 2020-12-04 + */ +public class MainAbilitySlice extends AbilitySlice { + private static final String TAG = MainAbility.class.getSimpleName(); + private static final String INTENT_STARTTIME_PARAM = "intetn_starttime_param"; + private CommonProvider commonProvider; + private AdvertisementProvider advertisementProvider; + private PageSlider advPageSlider; + private ScheduledExecutorService scheduledExecutor; + private int currentPageIndex = 0; + private Runnable slidTask; + + @Override + protected void onStart(Intent intent) { + super.onStart(intent); + setUIContent(ResourceTable.Layout_video); + initContent(); + } + + private void initContent() { + initScheduledExecutor(); + initAdvertisement(); + initList(); + startSlidTimer(); + } + + private void initScheduledExecutor() { + slidTask = () -> getUITaskDispatcher().asyncDispatch(() -> { + if (currentPageIndex == advertisementProvider.getCount()) { + currentPageIndex = 0; + } else { + currentPageIndex++; + } + advPageSlider.setCurrentPage(currentPageIndex); + }); + scheduledExecutor = new ScheduledThreadPoolExecutor(1); + } + + private void initList() { + LogUtil.info(TAG, "begin updateTableView tab view"); + Text playTitle = null; + if (findComponentById(ResourceTable.Id_video_play_title) instanceof Text) { + playTitle = (Text) findComponentById(ResourceTable.Id_video_play_title); + } + Font.Builder fb = new Font.Builder(VideoTabStyle.BOLD_FONT_NAME); + fb.setWeight(Font.BOLD); + Font newFont = fb.build(); + playTitle.setFont(newFont); + commonProvider = new CommonProvider( + MediaUtil.getPlayListMos(), + getContext(), + ResourceTable.Layout_recommend_gv_item) { + @Override + protected void convert(ViewProvider holder, VideoListMo item, int position) { + holder.setText(ResourceTable.Id_name_tv, item.getName()); + holder.setText(ResourceTable.Id_content_tv, item.getDescription()); + holder.setImageResource(ResourceTable.Id_image_iv, item.getSourceId()); + } + }; + ListContainer playListContainer = null; + if (findComponentById(ResourceTable.Id_video_list_play_view) instanceof ListContainer) { + playListContainer = (ListContainer) findComponentById(ResourceTable.Id_video_list_play_view); + } + playListContainer.setItemProvider(commonProvider); + playListContainer.setItemClickedListener((listContainer, component, index, position) -> startFa()); + } + + private void initAdvertisement() { + advertisementProvider = new AdvertisementProvider<>(getAdvertisementComponents()); + Component advViewPager = findComponentById(ResourceTable.Id_video_advertisement_viewpager); + if (advViewPager instanceof PageSlider) { + advPageSlider = (PageSlider) advViewPager; + advPageSlider.setProvider(advertisementProvider); + advPageSlider.setClickedListener(component -> startFa()); + } else { + LogUtil.debug(TAG, "initAdvertisement failed, advertisement_viewpager is not PageSlider"); + } + PageSliderIndicator advIndicator = null; + if (findComponentById(ResourceTable.Id_video_advertisement_indicator) instanceof PageSliderIndicator) { + advIndicator = (PageSliderIndicator) findComponentById( + ResourceTable.Id_video_advertisement_indicator); + } + advIndicator.setItemOffset(VideoTabStyle.INDICATOR_OFFSET); + ShapeElement normalDrawable = new ShapeElement(); + normalDrawable.setRgbColor(RgbColor.fromRgbaInt(Color.WHITE.getValue())); + normalDrawable.setAlpha(VideoTabStyle.INDICATOR_NORMA_ALPHA); + normalDrawable.setShape(ShapeElement.OVAL); + normalDrawable.setBounds(0, 0, VideoTabStyle.INDICATOR_BONDS, VideoTabStyle.INDICATOR_BONDS); + ShapeElement selectedDrawable = new ShapeElement(); + selectedDrawable.setRgbColor(RgbColor.fromRgbaInt(Color.WHITE.getValue())); + selectedDrawable.setShape(ShapeElement.OVAL); + selectedDrawable.setBounds(0, 0, VideoTabStyle.INDICATOR_BONDS, VideoTabStyle.INDICATOR_BONDS); + advIndicator.setItemElement(normalDrawable, selectedDrawable); + advIndicator.setViewPager((PageSlider) advViewPager); + } + + private void startFa() { + Intent intent = new Intent(); + Operation operation = new Intent.OperationBuilder().withBundleName(getBundleName()) + .withAbilityName(PlayerAbility.class.getName()).build(); + intent.setOperation(operation); + intent.setParam(INTENT_STARTTIME_PARAM, 0); + startAbility(intent); + } + + private List getAdvertisementComponents() { + List advertisementMos = MediaUtil.getVideoAdvertisementInfo(); + List componentList = new ArrayList<>(advertisementMos.size()); + Font.Builder fb = new Font.Builder(VideoTabStyle.BOLD_FONT_NAME); + fb.setWeight(Font.BOLD); + Font newFont = fb.build(); + for (AdvertisementMo advertisementMo : advertisementMos) { + Component advRootView = LayoutScatter.getInstance(getContext()).parse( + ResourceTable.Layout_video_advertisement_item, null, false); + Image imgTemp = null; + if (advRootView.findComponentById(ResourceTable.Id_video_advertisement_poster) instanceof Image) { + imgTemp = (Image) advRootView.findComponentById(ResourceTable.Id_video_advertisement_poster); + } + imgTemp.setPixelMap(advertisementMo.getSourceId()); + Text titleTmp = null; + if (advRootView.findComponentById(ResourceTable.Id_video_advertisement_title) instanceof Text) { + titleTmp = (Text) advRootView.findComponentById(ResourceTable.Id_video_advertisement_title); + } + titleTmp.setText(advertisementMo.getDescription()); + titleTmp.setFont(newFont); + componentList.add(advRootView); + } + + return componentList; + } + + private void startSlidTimer() { + scheduledExecutor.scheduleAtFixedRate(slidTask, VideoTabStyle.ADVERTISEMENT_SLID_PROID, + VideoTabStyle.ADVERTISEMENT_SLID_DELAY, TimeUnit.SECONDS); + } + + @Override + public void onActive() { + super.onActive(); + } + + @Override + public void onInactive() { + super.onInactive(); + LogUtil.info(TAG, "is onInactive"); + } + + @Override + public void onForeground(Intent intent) { + super.onForeground(intent); + LogUtil.info(TAG, "is onForeground"); + } + + @Override + public void onBackground() { + super.onBackground(); + LogUtil.info(TAG, "is onBackground"); + } + + @Override + public void onStop() { + super.onStop(); + LogUtil.info(TAG, "is onStop"); + } + + @Override + protected void onBackPressed() { + LogUtil.info(TAG, "is onBackPressed"); + super.onBackPressed(); + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/slice/SimplePlayerAbilitySlice.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/slice/SimplePlayerAbilitySlice.java new file mode 100644 index 0000000000000000000000000000000000000000..af1d509cee196e48e31e68a856ccb14d54ead1c3 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/slice/SimplePlayerAbilitySlice.java @@ -0,0 +1,308 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.slice; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.ability.IAbilityConnection; +import ohos.aafwk.content.Intent; +import ohos.aafwk.content.Operation; +import ohos.agp.components.Button; +import ohos.agp.components.Component; +import ohos.agp.components.DependentLayout; +import ohos.agp.components.Image; +import ohos.agp.components.ListContainer; +import ohos.app.dispatcher.task.TaskPriority; +import ohos.bundle.AbilityInfo; +import ohos.bundle.ElementName; +import ohos.codelabs.distributedvideo.ResourceTable; +import ohos.codelabs.distributedvideo.VideoMigrateService; +import ohos.codelabs.distributedvideo.component.RemoteController; +import ohos.codelabs.distributedvideo.component.SlidePopupWindow; +import ohos.codelabs.distributedvideo.component.Toast; +import ohos.codelabs.distributedvideo.manager.idl.ImplVideoMigration; +import ohos.codelabs.distributedvideo.manager.idl.VideoMigrationStub; +import ohos.codelabs.distributedvideo.player.HmPlayer; +import ohos.codelabs.distributedvideo.player.api.ImplPlayer; +import ohos.codelabs.distributedvideo.player.constant.Constants; +import ohos.codelabs.distributedvideo.player.constant.PlayerStatu; +import ohos.codelabs.distributedvideo.player.view.PlayerLoading; +import ohos.codelabs.distributedvideo.player.view.PlayerView; +import ohos.codelabs.distributedvideo.player.view.SimplePlayerController; +import ohos.codelabs.distributedvideo.provider.CommonProvider; +import ohos.codelabs.distributedvideo.provider.ViewProvider; +import ohos.codelabs.distributedvideo.util.AbilitySliceRouteUtil; +import ohos.codelabs.distributedvideo.util.LogUtil; +import ohos.codelabs.distributedvideo.util.ScreenUtils; +import ohos.distributedschedule.interwork.DeviceInfo; +import ohos.distributedschedule.interwork.DeviceManager; +import ohos.rpc.IRemoteObject; +import ohos.rpc.RemoteException; + +import java.util.ArrayList; +import java.util.List; + +/** + * PlayerAbilitySlice + * + * @since 2020-12-04 + */ +public class SimplePlayerAbilitySlice extends AbilitySlice { + private static final String TAG = SimplePlayerAbilitySlice.class.getSimpleName(); + private static final int TOAST_DURATION = 3000; + private static ImplPlayer player; + private RemoteController remoteController; + private ImplVideoMigration implVideoMigration; + private DependentLayout parentLayout; + private ListContainer deviceListContainer; + private Image tv; + private SlidePopupWindow transWindow; + private List devices = new ArrayList<>(0); + private int startMillisecond; + private String url = "entry/resources/base/media/gubeishuizhen.mp4"; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_simple_video_play_layout); + AbilitySliceRouteUtil.getInstance().addRoute(this); + startMillisecond = intent.getIntParam(Constants.INTENT_STARTTIME_PARAM, 0); + player = new HmPlayer.Builder(this).setFilePath(url).setStartMillisecond(startMillisecond).create(); + player.getLifecycle().onStart(); + initComponent(); + initListener(); + } + + /** + * getImplPlayer + * + * @return ImplPlayer + */ + public static ImplPlayer getImplPlayer() { + return player; + } + + private void initComponent() { + if (findComponentById(ResourceTable.Id_parent) instanceof DependentLayout) { + parentLayout = (DependentLayout) findComponentById(ResourceTable.Id_parent); + transWindow = new SlidePopupWindow.Builder(this).create(ResourceTable.Layout_trans_slide); + if (transWindow.findComponentById(ResourceTable.Id_device_list_container) instanceof ListContainer) { + deviceListContainer = + (ListContainer) transWindow.findComponentById(ResourceTable.Id_device_list_container); + } + remoteController = new RemoteController(this); + parentLayout.addComponent(transWindow); + parentLayout.addComponent(remoteController); + } + if (findComponentById(ResourceTable.Id_player_view) instanceof PlayerView) { + PlayerView playerView = (PlayerView) findComponentById(ResourceTable.Id_player_view); + playerView.bind(player); + } + if (findComponentById(ResourceTable.Id_loading_view) instanceof PlayerLoading) { + PlayerLoading playerLoading = (PlayerLoading) findComponentById(ResourceTable.Id_loading_view); + playerLoading.bind(player); + } + if (findComponentById(ResourceTable.Id_controller_view) instanceof SimplePlayerController) { + SimplePlayerController simplePlayerController = + (SimplePlayerController) findComponentById(ResourceTable.Id_controller_view); + if (simplePlayerController.findComponentById(ResourceTable.Id_tv) instanceof Image) { + tv = (Image) simplePlayerController.findComponentById(ResourceTable.Id_tv); + } + simplePlayerController.bind(player); + } + } + + private void initListener() { + tv.setClickedListener(component -> { + initDevices(); + showDeviceList(); + }); + transWindow.setPopupWindowListener(new SlidePopupWindow.PopupWindowListener() { + @Override + public void windowShow() { + player.pause(); + } + + @Override + public void windowDismiss() { + if (player.getPlayerStatu() == PlayerStatu.PAUSE) { + player.resume(); + } + } + }); + setRemoteControllerCallback(); + } + + private void setRemoteControllerCallback() { + remoteController.setRemoteControllerCallback(new MyRemoteControllerListener()); + } + + /** + * MyRemoteControllerListener + * + * @since 2020-12-04 + */ + private class MyRemoteControllerListener implements RemoteController.RemoteControllerListener { + @Override + public void controllerShow() { + } + + @Override + public void controllerDismiss() { + int progress = 0; + try { + if (implVideoMigration != null) { + progress = implVideoMigration.flyOut(); + } + } catch (RemoteException e) { + LogUtil.error(TAG, "RemoteException occurs"); + } + player.reload(url, progress); + } + + @Override + public void sendControl(int code, int extra) { + try { + if (implVideoMigration != null) { + implVideoMigration.playControl(code, extra); + } + } catch (RemoteException e) { + LogUtil.error(TAG, "RemoteException occurs "); + } + } + } + + private void initDevices() { + if (devices.size() > 0) { + devices.clear(); + } + List deviceInfos = DeviceManager.getDeviceList(DeviceInfo.FLAG_GET_ONLINE_DEVICE); + devices.addAll(deviceInfos); + } + + private void showDeviceList() { + CommonProvider commonProvider = new CommonProvider( + devices, + getContext(), + ResourceTable.Layout_device_list_item) { + @Override + protected void convert(ViewProvider holder, DeviceInfo item, int position) { + holder.setText(ResourceTable.Id_device_text, item.getDeviceName()); + Button clickButton = holder.getView(ResourceTable.Id_device_text); + clickButton.setText(item.getDeviceName()); + clickButton.setClickedListener(component -> { + transWindow.hide(); + startAbilityFa(item.getDeviceId()); + }); + } + }; + deviceListContainer.setItemProvider(commonProvider); + commonProvider.notifyDataChanged(); + transWindow.show(); + } + + private void startAbilityFa(String devicesId) { + Intent intent = new Intent(); + Operation operation = + new Intent.OperationBuilder() + .withDeviceId(devicesId) + .withBundleName(getBundleName()) + .withAbilityName(VideoMigrateService.class.getName()) + .withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE) + .build(); + intent.setOperation(operation); + boolean connectFlag = connectAbility(intent, new IAbilityConnection() { + @Override + public void onAbilityConnectDone(ElementName elementName, IRemoteObject remoteObject, int extra) { + implVideoMigration = VideoMigrationStub.asInterface(remoteObject); + try { + implVideoMigration.flyIn(startMillisecond); + } catch (RemoteException e) { + LogUtil.error(TAG, "connect successful,but have remote exception"); + } + } + + @Override + public void onAbilityDisconnectDone(ElementName elementName, int extra) { + disconnectAbility(this); + } + }); + if (connectFlag) { + Toast.toast(this, "transmit successful!", TOAST_DURATION); + remoteController.show(); + startMillisecond = player.getCurrentPosition(); + player.release(); + } else { + Toast.toast(this, "transmit failed!Please try again later.", TOAST_DURATION); + } + } + + @Override + public void onActive() { + super.onActive(); + getGlobalTaskDispatcher(TaskPriority.DEFAULT).delayDispatch(() -> player.play(), Constants.NUMBER_1000); + } + + @Override + protected void onInactive() { + LogUtil.info(TAG, "onInactive is called"); + super.onInactive(); + } + + @Override + public void onForeground(Intent intent) { + if (remoteController == null || !remoteController.isShown()) { + player.getLifecycle().onForeground(); + } + super.onForeground(intent); + } + + @Override + protected void onBackground() { + LogUtil.info(TAG, "onBackground is called"); + if (remoteController == null || !remoteController.isShown()) { + player.getLifecycle().onBackground(); + } + super.onBackground(); + } + + @Override + protected void onBackPressed() { + if (remoteController != null && remoteController.isShown()) { + remoteController.hide(); + } else { + super.onBackPressed(); + } + } + + @Override + protected void onStop() { + LogUtil.info(TAG, "onStop is called"); + AbilitySliceRouteUtil.getInstance().removeRoute(this); + player.getLifecycle().onStop(); + super.onStop(); + } + + @Override + protected void onOrientationChanged(AbilityInfo.DisplayOrientation displayOrientation) { + super.onOrientationChanged(displayOrientation); + int screenWidth = ScreenUtils.getScreenWidth(this); + parentLayout.setWidth(screenWidth); + tv.setVisibility(displayOrientation == AbilityInfo.DisplayOrientation.LANDSCAPE + ? Component.HIDE + : Component.VISIBLE); + player.openGesture(displayOrientation == AbilityInfo.DisplayOrientation.LANDSCAPE); + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/AbilitySliceRouteUtil.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/AbilitySliceRouteUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..2f7bcc3fc1478a48fadcb6503495fe2c4a3e2094 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/AbilitySliceRouteUtil.java @@ -0,0 +1,109 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.util; + +import ohos.aafwk.ability.AbilitySlice; + +import java.util.ArrayList; +import java.util.List; + +/** + * AbilitySliceRoute util + * + * @since 2021-05-04 + */ +public class AbilitySliceRouteUtil { + private static AbilitySliceRouteUtil instance; + + private List routes; + + private AbilitySliceRouteUtil() { + routes = new ArrayList<>(0); + } + + /** + * initialization AbilitySliceRouteUtil + * + * @return AbilitySliceRouteUtil + */ + public static synchronized AbilitySliceRouteUtil getInstance() { + if (instance == null) { + instance = new AbilitySliceRouteUtil(); + } + return instance; + } + + /** + * add route + * + * @param slice slice + */ + public void addRoute(AbilitySlice slice) { + routes.add(slice); + } + + /** + * remove Route + * + * @param slice slice + */ + public void removeRoute(AbilitySlice slice) { + for (int i = routes.size() - 1; i >= 0; i--) { + if (routes.get(i).equals(slice)) { + routes.remove(routes.get(i)); + break; + } + } + } + + /** + * back to AbilitySlice which name is sliceName + * + * @param sliceName sliceName + */ + public void backTo(String sliceName) { + List slices = new ArrayList<>(0); + for (int i = routes.size() - 1; i >= 0; i--) { + if (routes.get(i).getClass().getName().equals(sliceName)) { + break; + } else { + slices.add(routes.get(i)); + } + } + if (slices.size() > 0) { + terminateSlices(slices); + } + } + + /** + * terminate AbilitySlices from slices + * + */ + public void terminateSlices() { + terminateSlices(routes); + } + + /** + * terminate AbilitySlices from slices + * + * @param slices slices + */ + private void terminateSlices(List slices) { + for (int i = slices.size() - 1; i >= 0; i--) { + slices.get(i).terminate(); + } + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/LogUtil.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/LogUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..61c9436d34b3597d43fa6d49a1621cfcc9391354 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/LogUtil.java @@ -0,0 +1,66 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.util; + +import ohos.hiviewdfx.HiLog; +import ohos.hiviewdfx.HiLogLabel; + +/** + * Log util + * + * @since 2020-12-04 + * + */ +public class LogUtil { + private static final String TAG_LOG = "LogUtil"; + + private static final HiLogLabel LABEL_LOG = new HiLogLabel(0, 0, LogUtil.TAG_LOG); + + private static final String LOG_FORMAT = "%{public}s: %{public}s"; + + private LogUtil() { + } + + /** + * Print debug log + * + * @param tag log tag + * @param msg log message + */ + public static void debug(String tag, String msg) { + HiLog.debug(LABEL_LOG, LOG_FORMAT, tag, msg); + } + + /** + * Print info log + * + * @param tag log tag + * @param msg log message + */ + public static void info(String tag, String msg) { + HiLog.info(LABEL_LOG, LOG_FORMAT, tag, msg); + } + + /** + * Print error log + * + * @param tag log tag + * @param msg log message + */ + public static void error(String tag, String msg) { + HiLog.error(LABEL_LOG, LOG_FORMAT, tag, msg); + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/MediaUtil.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/MediaUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..528d09457872b99546d2566f8ddb0ca936018940 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/MediaUtil.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.util; + +import ohos.codelabs.distributedvideo.ResourceTable; +import ohos.codelabs.distributedvideo.data.AdvertisementMo; +import ohos.codelabs.distributedvideo.data.VideoListMo; + +import java.util.ArrayList; +import java.util.List; + +/** + * Media util + * + * @since 2020-12-04 + */ +public class MediaUtil { + private static List videoAdvertisementMos = new ArrayList<>(0); + private static List playListMos = new ArrayList<>(0); + + private MediaUtil() { + } + + static { + videoAdvertisementMos.add(new AdvertisementMo(ResourceTable.Media_video_ad0, "green")); + videoAdvertisementMos.add(new AdvertisementMo(ResourceTable.Media_video_ad2, "yellow")); + videoAdvertisementMos.add(new AdvertisementMo(ResourceTable.Media_video_ad3, "red")); + playListMos.add(new VideoListMo(ResourceTable.Media_video_list0, + "landscape", "waterfall")); + playListMos.add(new VideoListMo(ResourceTable.Media_video_list2, "child", "cute")); + playListMos.add(new VideoListMo(ResourceTable.Media_video_list1, "show", "drone")); + } + + /** + * get the advertisement constructor + * + * @return advertisementMos + */ + public static List getVideoAdvertisementInfo() { + return videoAdvertisementMos; + } + + /** + * get VideoListMos + * + * @return VideoListMo + */ + public static List getPlayListMos() { + return playListMos; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/ScreenUtils.java b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/ScreenUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..ed9c5ea635f00012e1df2e01b4b1c3dda92059e9 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/java/ohos/codelabs/distributedvideo/util/ScreenUtils.java @@ -0,0 +1,121 @@ +/* + * 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. + */ + +package ohos.codelabs.distributedvideo.util; + +import ohos.agp.utils.Point; +import ohos.agp.window.service.Display; +import ohos.agp.window.service.DisplayAttributes; +import ohos.agp.window.service.DisplayManager; +import ohos.app.Context; +import ohos.global.configuration.DeviceCapability; + +import java.util.Optional; + +/** + * ScreenUtils + * + * @since 2020-12-04 + */ +public class ScreenUtils { + private ScreenUtils() { + } + + /** + * getScreenHeight + * + * @param context context + * @return int + */ + public static int getScreenHeight(Context context) { + DisplayManager displayManager = DisplayManager.getInstance(); + Optional optDisplay = displayManager.getDefaultDisplay(context); + Point point = new Point(0, 0); + if (!optDisplay.isPresent()) { + return (int) point.position[1]; + } else { + Display display = optDisplay.get(); + display.getSize(point); + return (int) point.position[1]; + } + } + + /** + * getScreenWidth + * + * @param context context + * @return int + */ + public static int getScreenWidth(Context context) { + DisplayManager displayManager = DisplayManager.getInstance(); + Optional optDisplay = displayManager.getDefaultDisplay(context); + Point point = new Point(0, 0); + if (!optDisplay.isPresent()) { + return (int) point.position[0]; + } else { + Display display = optDisplay.get(); + display.getSize(point); + return (int) point.position[0]; + } + } + + /** + * vp转像素 + * + * @param context context + * @param vp vp + * @return px + */ + public static int vp2px(Context context, float vp) { + DisplayAttributes attributes = DisplayManager.getInstance().getDefaultDisplay(context).get().getAttributes(); + return (int) (vp * attributes.densityPixels); + } + + /** + * 像素转vp + * + * @param context context + * @param px px + * @return vp + */ + public static int px2vp(Context context, float px) { + DisplayAttributes attributes = DisplayManager.getInstance().getDefaultDisplay(context).get().getAttributes(); + return (int) (px / attributes.densityPixels); + } + + /** + * dp2px + * + * @param context context + * @param size size + * @return int + */ + public static int dp2px(Context context, int size) { + int density = context.getResourceManager().getDeviceCapability().screenDensity / DeviceCapability.SCREEN_MDPI; + return size * density; + } + + /** + * px2dip + * + * @param context context + * @param size size + * @return int + */ + public static int px2dip(Context context, int size) { + int density = context.getResourceManager().getDeviceCapability().screenDensity / DeviceCapability.SCREEN_MDPI; + return size / density; + } +} diff --git a/DistributedVideoCodelab/entry/src/main/resources/base/element/colors.json b/DistributedVideoCodelab/entry/src/main/resources/base/element/colors.json index 2ee40bdd48dd9e9add158d97f9efcea24ce975f8..7464b8f07e12495cd833b93175ebbfe955ddf50b 100644 --- a/DistributedVideoCodelab/entry/src/main/resources/base/element/colors.json +++ b/DistributedVideoCodelab/entry/src/main/resources/base/element/colors.json @@ -15,6 +15,9 @@ { "name": "half_transparent", "value": "#55000000" + }, { + "name": "dark_grey", + "value": "#282828" } ] } \ No newline at end of file diff --git a/DistributedVideoCodelab/entry/src/main/resources/base/graphic/button_normal_ability_main.xml b/DistributedVideoCodelab/entry/src/main/resources/base/graphic/button_normal_ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..c0c0a3df480fa387a452b9c40ca191cc918a3fc0 --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/resources/base/graphic/button_normal_ability_main.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/DistributedVideoCodelab/entry/src/main/resources/base/graphic/button_pressed_ability_main.xml b/DistributedVideoCodelab/entry/src/main/resources/base/graphic/button_pressed_ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..59c0141c2b5665c2d1d883022209208eb9290e3b --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/resources/base/graphic/button_pressed_ability_main.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/DistributedVideoCodelab/entry/src/main/resources/base/graphic/selector_ability_main.xml b/DistributedVideoCodelab/entry/src/main/resources/base/graphic/selector_ability_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..603ed1fbca321ba08d2f00aa83089b9cfc79ea1f --- /dev/null +++ b/DistributedVideoCodelab/entry/src/main/resources/base/graphic/selector_ability_main.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/DistributedVideoCodelab/entry/src/main/resources/base/layout/device_list_item.xml b/DistributedVideoCodelab/entry/src/main/resources/base/layout/device_list_item.xml index 760532306fa8c16871c4985672412cfe2d0bfe72..dec41ab71c82739688c4de14c1c2a122496b32eb 100644 --- a/DistributedVideoCodelab/entry/src/main/resources/base/layout/device_list_item.xml +++ b/DistributedVideoCodelab/entry/src/main/resources/base/layout/device_list_item.xml @@ -1,14 +1,16 @@ - - - + +