From b799f883710f85e58fed6e58b0a21a083781d29b Mon Sep 17 00:00:00 2001 From: sunlian Date: Mon, 14 Oct 2024 10:04:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=A1=8C=E9=9D=A2=E5=8D=A1?= =?UTF-8?q?=E7=89=87=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: sunlian --- scenario/MusicPlayerOnline/README_zh.md | 2 +- .../main/ets/constants/ServerConstants.ets | 40 +-- .../main/ets/entryability/EntryAbility.ets | 60 +++- .../ets/entryformability/EntryFormAbility.ets | 111 +++++++ .../src/main/ets/manager/PlayerManager.ets | 49 +++- .../src/main/ets/widget/pages/WidgetCard.ets | 275 ++++++++++++++++++ .../entry/src/main/module.json5 | 24 +- .../main/resources/base/element/color.json | 16 + .../main/resources/base/element/float.json | 40 +++ .../main/resources/base/element/string.json | 24 ++ .../main/resources/base/media/ic_widget.png | Bin 0 -> 5831 bytes .../resources/base/profile/form_config.json | 25 ++ .../main/resources/en_US/element/string.json | 24 ++ .../main/resources/zh_CN/element/string.json | 24 ++ 14 files changed, 680 insertions(+), 34 deletions(-) create mode 100644 scenario/MusicPlayerOnline/entry/src/main/ets/entryformability/EntryFormAbility.ets create mode 100644 scenario/MusicPlayerOnline/entry/src/main/ets/widget/pages/WidgetCard.ets create mode 100644 scenario/MusicPlayerOnline/entry/src/main/resources/base/element/float.json create mode 100644 scenario/MusicPlayerOnline/entry/src/main/resources/base/media/ic_widget.png create mode 100644 scenario/MusicPlayerOnline/entry/src/main/resources/base/profile/form_config.json diff --git a/scenario/MusicPlayerOnline/README_zh.md b/scenario/MusicPlayerOnline/README_zh.md index 2ce0a9e7f..3115c6067 100644 --- a/scenario/MusicPlayerOnline/README_zh.md +++ b/scenario/MusicPlayerOnline/README_zh.md @@ -94,7 +94,7 @@ 9. 进度条拖动 10. 边听边存、离线播放 11. 歌词 - 12. 桌面播放卡片 + 12. 桌面播放卡片 (已完成) 13. 歌曲分类: 热门歌手 (已完成) 14. 其他平台歌曲推荐、播放 15. 音频焦点处理 diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/constants/ServerConstants.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/constants/ServerConstants.ets index 975fc06d4..4a6968145 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/constants/ServerConstants.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/constants/ServerConstants.ets @@ -20,7 +20,7 @@ export default class ServerConstants { /** * server host ,replace with your owen server address */ - static readonly SERVER_HOST = 'http://192.168.13.29:8000/'; + static readonly SERVER_HOST = 'http://192.168.13.110:8000/'; /** * custom list URL */ @@ -83,33 +83,37 @@ export default class ServerConstants { /** * 首页播放状态更新消息 */ - static readonly MAIN_UPDATE_TIME = '01'; - static readonly MAIN_UPDATE_STATE = '02'; - static readonly MAIN_SHOW_PLAYLIST = '03'; + static readonly MAIN_UPDATE_TIME = 'MAIN_UPDATE_TIME'; + static readonly MAIN_UPDATE_STATE = 'MAIN_UPDATE_STATE'; + static readonly MAIN_SHOW_PLAYLIST = 'MAIN_SHOW_PLAYLIST'; /** * 详情页播放状态更新消息 */ - static readonly DETAIL_UPDATE_TIME = '10'; - static readonly DETAIL_UPDATE_STATE = '11'; - static readonly DETAIL_UPDATE_FAVOR_AND_QUALITY = '12'; + static readonly DETAIL_UPDATE_TIME = 'DETAIL_UPDATE_TIME'; + static readonly DETAIL_UPDATE_STATE = 'DETAIL_UPDATE_STATE'; + static readonly DETAIL_UPDATE_FAVOR_AND_QUALITY = 'DETAIL_UPDATE_FAVOR_AND_QUALITY'; + /** + * 卡片更新消息 + */ + static readonly CARD_UPDATE_STATE = 'music.online.card.update'; /** * 播放列表播放状态更新消息 */ - static readonly PLAYLIST_UPDATE_STATE = '20'; - static readonly PLAYLIST_UPDATE_CHANGED = '21'; + static readonly PLAYLIST_UPDATE_STATE = 'PLAYLIST_UPDATE_STATE'; + static readonly PLAYLIST_UPDATE_CHANGED = 'PLAYLIST_UPDATE_CHANGED'; //首页列表更新消息 - static readonly UPDATE_USER_LIST = '8'; - static readonly UPDATE_USER_LIST_RECOMMEND = '80'; - static readonly UPDATE_USER_LIST_CUSTOM = '81'; - static readonly UPDATE_USER_LIST_RECENT = '82'; - static readonly UPDATE_USER_LIST_FAVOR = '83'; - static readonly UPDATE_USER_LIST_SEARCH = '84'; + static readonly UPDATE_USER_LIST = 'UPDATE_USER_LIST'; + static readonly UPDATE_USER_LIST_RECOMMEND = 'UPDATE_USER_LIST_RECOMMEND'; + static readonly UPDATE_USER_LIST_CUSTOM = 'UPDATE_USER_LIST_CUSTOM'; + static readonly UPDATE_USER_LIST_RECENT = 'UPDATE_USER_LIST_RECENT'; + static readonly UPDATE_USER_LIST_FAVOR = 'UPDATE_USER_LIST_FAVOR'; + static readonly UPDATE_USER_LIST_SEARCH = 'UPDATE_USER_LIST_SEARCH'; //首页登录更新消息 - static readonly LOGIN_RESULT = '9' - static readonly LOGIN_RESULT_SUCCESS = '90' - static readonly LOGIN_RESULT_FAILED = '91' + static readonly LOGIN_RESULT = 'LOGIN_RESULT' + static readonly LOGIN_RESULT_SUCCESS = 'LOGIN_RESULT_SUCCESS' + static readonly LOGIN_RESULT_FAILED = 'LOGIN_RESULT_FAILED' /** * PLAYER LIST */ diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/entryability/EntryAbility.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/entryability/EntryAbility.ets index 9656d540e..0fe7f6422 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/entryability/EntryAbility.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/entryability/EntryAbility.ets @@ -19,12 +19,53 @@ import UIAbility from '@ohos.app.ability.UIAbility'; import Want from '@ohos.app.ability.Want'; import window from '@ohos.window'; import PlayerManager from '../manager/PlayerManager'; +import rpc from '@ohos.rpc'; +import HttpManager from '../manager/HttpManager'; + +const TAG: string = 'EntryAbility'; export default class EntryAbility extends UIAbility { onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { - AppStorage.setOrCreate('APPContext',this.context); - AppStorage.setOrCreate('PlayerManager', new PlayerManager()); - hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + AppStorage.setOrCreate('APPContext', this.context); + let aPlayerManager: PlayerManager = new PlayerManager(); + AppStorage.setOrCreate('PlayerManager', aPlayerManager); + try { + this.callee.on('play', (data: rpc.MessageSequence) => { + aPlayerManager.resume(); + return null; + }); + this.callee.on('pause', (data: rpc.MessageSequence) => { + aPlayerManager.pause(); + return null; + }); + this.callee.on('prev', (data: rpc.MessageSequence) => { + aPlayerManager.previous(); + return null; + }); + this.callee.on('next', (data: rpc.MessageSequence) => { + aPlayerManager.next(); + return null; + }); + this.callee.on('playMode', (data: rpc.MessageSequence) => { + aPlayerManager.setPlayMode(); + return null; + }); + this.callee.on('setFavor', (data: rpc.MessageSequence) => { + HttpManager.getInstance().set_favourite(); + return null; + }); + this.callee.on('formId', (data: rpc.MessageSequence) => { + let params: Record = JSON.parse(data.readString()); + if (params.formId !== undefined) { + console.info(TAG, 'params.formId:' + params.formId); + aPlayerManager.setFormId(params.formId); + } + return null; + }); + } catch (error) { + console.error('Failed to register callee on. Cause:' + JSON.stringify(error)); + } + console.info(TAG, 'Ability onCreate'); } onWindowStageCreate(windowStage: window.WindowStage): void { @@ -39,6 +80,19 @@ export default class EntryAbility extends UIAbility { }); } + onDestroy(): void { + try { + this.callee.off('play'); + this.callee.off('pause'); + this.callee.off('prev'); + this.callee.off('next'); + this.callee.off('formId'); + this.callee.off('playMode'); + } catch (error) { + console.error('Failed to register callee off. Cause:' + JSON.stringify(error)); + } + } + onWindowStageDestroy(): void { // Main window is destroyed, release UI related resources hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/entryformability/EntryFormAbility.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/entryformability/EntryFormAbility.ets new file mode 100644 index 000000000..14f20a504 --- /dev/null +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/entryformability/EntryFormAbility.ets @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { formBindingData, FormExtensionAbility, formInfo } from '@kit.FormKit'; +import { Want } from '@kit.AbilityKit'; +import Base from '@ohos.base'; +import formProvider from '@ohos.app.form.formProvider'; +import type fileFs from '@ohos.file.fs'; +import fs from '@ohos.file.fs'; +import http from '@ohos.net.http'; + +const TAG: string = 'EntryFormAbility'; + +export default class EntryFormAbility extends FormExtensionAbility { + + onAddForm(want: Want) { + // Called to return a FormBindingData object. + class DataObj1 { + formId: string = ''; + } + + let dataObj1 = new DataObj1(); + if (want.parameters && want.parameters['ohos.extra.param.key.form_identity'] !== undefined) { + let formId = want.parameters['ohos.extra.param.key.form_identity'].toString(); + dataObj1.formId = formId; + } + console.info("PlayerManager EntryFormAbility formId:" + dataObj1.formId); + return formBindingData.createFormBindingData(dataObj1); + } + + onCastToNormalForm(formId: string) { + // Called when the form provider is notified that a temporary form is successfully + // converted to a normal form. + } + + onUpdateForm(formId: string) { + // Called to notify the form provider to update a specified form. + } + + onFormEvent(formId: string, message: string) { + // 注意:FormExtensionAbility在触发生命周期回调时被拉起,仅能在后台存在5秒 + // 建议下载能快速下载完成的小文件,如在5秒内未下载完成,则此次网络图片无法刷新至卡片页面上 + let params: Record = JSON.parse(message) + console.info(TAG, "url is:" + params.info); + let tempDir = this.context.getApplicationContext().tempDir; + let fileName = 'file' + Date.now(); + let tmpFile = tempDir + '/' + fileName; + + let httpRequest = http.createHttp() + httpRequest.request(params.info, (err, data) => { + if (!err && data.responseCode == http.ResponseCode.OK) { + let imgFile = fs.openSync(tmpFile, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + fs.write(imgFile.fd, data.result as ArrayBuffer).then((writeLen: number) => { + console.info(TAG, "write data to file succeed and size is:" + writeLen); + }).catch((err: Base.BusinessError) => { + console.error(TAG, "write data to file failed with error message: " + err.message + ", error code: " + err.code); + }).finally(() => { + fs.closeSync(imgFile); + }); + + console.info(TAG, 'ArkTSCard download complete: %{public}s', tmpFile); + let file: fileFs.File; + let fileInfo: Record = {}; + try { + file = fs.openSync(tmpFile); + fileInfo[fileName] = file.fd; + } catch (e) { + console.error(TAG, `openSync failed: ${JSON.stringify(e as Base.BusinessError)}`); + } + + class FormDataClass { + imgName: string = fileName; + formImages: object = fileInfo; + } + + let formData = new FormDataClass(); + let formInfo = formBindingData.createFormBindingData(formData); + formProvider.updateForm(formId, formInfo).then(() => { + console.info(TAG, '%{public}s', 'FormAbility updateForm success.'); + }).catch((error: Base.BusinessError) => { + console.error(TAG, `FormAbility updateForm failed: ${JSON.stringify(error)}`); + }); + } else { + console.error(TAG, `ArkTSCard download task failed. Cause: ${JSON.stringify(err)}`); + } + httpRequest.destroy(); + }) + } + + onRemoveForm(formId: string) { + // Called to notify the form provider that a specified form has been destroyed. + } + + onAcquireFormState(want: Want) { + // Called to return a {@link FormState} object. + return formInfo.FormState.READY; + } + +}; \ No newline at end of file diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/manager/PlayerManager.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/manager/PlayerManager.ets index 0f17db0fd..a9e96f8c0 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/ets/manager/PlayerManager.ets +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/manager/PlayerManager.ets @@ -25,10 +25,14 @@ import wantAgent, { WantAgent } from '@ohos.app.ability.wantAgent'; import common from '@ohos.app.ability.common'; import HttpManager from './HttpManager'; import PlayListData from '../model/PlayListData'; +import Base from '@ohos.base'; +import formProvider from '@ohos.app.form.formProvider'; +import formBindingData from '@ohos.app.form.formBindingData'; export default class PlayerManager { private tag: string = 'PlayerManager'; + private formId: string = '1234567890'; private isSeek: boolean = false; private avPlayer: media.AVPlayer | undefined = undefined; private list: AudioData[] = []; @@ -36,11 +40,11 @@ export default class PlayerManager { private favourList: AudioData[] = []; private currentTime: number = 0; private currentDuration: number = 0; - private item: AudioData = new AudioData('', '', ''); + private item: AudioData = new AudioData('未播放', '--', ''); private listPosition: number = 0; private state: string = ServerConstants.PLAYER_STATE_UNKNOWN; private listTitle: string = ServerConstants.LIST_SONG_NO_PLAYING; - private playMode: number | undefined = PLAY_MODE.REPEAT; + private playMode: number = PLAY_MODE.REPEAT; private shuffleIndex: number[] = []; private emitterOptions: emitter.Options = { priority: emitter.EventPriority.HIGH @@ -91,10 +95,11 @@ export default class PlayerManager { emitter.emit(ServerConstants.MAIN_UPDATE_STATE, this.emitterOptions, eventData); emitter.emit(ServerConstants.DETAIL_UPDATE_STATE, this.emitterOptions, eventData); emitter.emit(ServerConstants.PLAYLIST_UPDATE_STATE, this.emitterOptions, eventData); + this.updateCard(); switch (state) { case ServerConstants.PLAYER_STATE_IDLE: // 成功调用reset接口后触发该状态机上报 console.info('PlayerManager state idle called.'); - //avPlayer.release(); // 调用release接口销毁实例对象 + //avPlayer.release(); // 调用release接口销毁实例对象 break; case ServerConstants.PLAYER_STATE_INITIALIZED: // avplayer 设置播放源后触发该状态上报 console.info('PlayerManager state initialized called.'); @@ -114,12 +119,12 @@ export default class PlayerManager { break; case ServerConstants.PLAYER_STATE_COMPLETED: // 播放结束后触发该状态机上报 console.info('PlayerManager state completed called.'); - //avPlayer.stop(); //调用播放结束接口 + //avPlayer.stop(); //调用播放结束接口 this.next(); break; case ServerConstants.PLAYER_STATE_STOPPED: // stop接口成功调用后触发该状态机上报 console.info('PlayerManager state stopped called.'); - //this.stopContinuousTask(); + //this.stopContinuousTask(); this.currentTime = 0; Logger.info(this.tag, 'Stop:' + this.item.title); avPlayer.reset(); // 调用reset接口初始化avplayer状态 @@ -317,6 +322,7 @@ export default class PlayerManager { this.playMode = PLAY_MODE.REPEAT; break; } + this.updatePlayMode(); return this.playMode; } @@ -324,12 +330,18 @@ export default class PlayerManager { return this.item; } + setFormId(formId: string) { + this.formId = formId; + this.updateCard(); + } + setItemQuality(quality: string) { this.item.quality = quality; } setItemFavor(isFavor: boolean) { this.item.isFavor = isFavor; + this.updateCard(); } setExploreList(aPlayListData: PlayListData) { @@ -349,9 +361,6 @@ export default class PlayerManager { } getPlayMode(): number { - if (this.playMode === undefined) { - return PLAY_MODE.REPEAT; - } return this.playMode; } @@ -445,5 +454,29 @@ export default class PlayerManager { console.error(`PlayerManager terminateSelf failed, code is ${code}, message is ${message}`); } } + + updateCard() { + let formData: Record = { + 'audioItem': this.item, + 'isPlaying': this.state, + }; + let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); + formProvider.updateForm(this.formId, formMsg).then(() => { + console.info('FormAbility updateForm success.'); + }).catch((error: Base.BusinessError) => { + console.info(`Operation updateForm failed. Cause: ${JSON.stringify(error)}`); + }) + } + updatePlayMode() { + let formData: Record = { + 'playMode': this.playMode, + }; + let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); + formProvider.updateForm(this.formId, formMsg).then(() => { + console.info('FormAbility updateForm success.'); + }).catch((error: Base.BusinessError) => { + console.info(`Operation updateForm failed. Cause: ${JSON.stringify(error)}`); + }) + } } diff --git a/scenario/MusicPlayerOnline/entry/src/main/ets/widget/pages/WidgetCard.ets b/scenario/MusicPlayerOnline/entry/src/main/ets/widget/pages/WidgetCard.ets new file mode 100644 index 000000000..f0f8ad3ea --- /dev/null +++ b/scenario/MusicPlayerOnline/entry/src/main/ets/widget/pages/WidgetCard.ets @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import AudioData from '../../model/AudioData'; +import ServerConstants from '../../constants/ServerConstants'; +import { PLAY_MODE } from '../../constants/PlayMode'; + +let storageUpdateByMsg = new LocalStorage(); +const TAG: string = 'MusicWidgetCard' + +@Entry(storageUpdateByMsg) +@Component +struct WidgetCard { + /* + * The display priority value is 1. + */ + readonly DISPLAY_PRIORITY_ONE: number = 1; + /* + * The display priority value is 2. + */ + readonly DISPLAY_PRIORITY_TWO: number = 2; + /* + * The width or height full percentage setting. + */ + readonly FULL_PERCENT: string = '100%'; + /* + * The action type. + */ + readonly ACTION_TYPE: string = 'router'; + /* + * The ability name. + */ + readonly ABILITY_NAME: string = 'EntryAbility'; + /* + * The maxLinesValue. + */ + readonly MAX_LINES_VALUE: number = 1; + @LocalStorageProp('formId') formId: string = ''; + @LocalStorageProp('audioItem') audioItem: AudioData = new AudioData('未播放', '--', '') + @LocalStorageProp('isPlaying') isPlaying: string = ServerConstants.PLAYER_STATE_UNKNOWN; + @LocalStorageProp('imgName') imgName: string = ''; + private downloadImgId: string = '' + @LocalStorageProp('playMode') playMode: number = PLAY_MODE.REPEAT; + + aboutToAppear(): void { + postCardAction(this, { + 'action': 'call', + 'abilityName': this.ABILITY_NAME, + 'params': { + 'method': 'formId', + 'formId': this.formId, + } + }); + } + + build() { + Stack({ alignContent: Alignment.TopStart }) { + Row() { + } + .width(this.FULL_PERCENT) + .height(this.FULL_PERCENT) + .displayPriority(this.DISPLAY_PRIORITY_ONE) + .backgroundImage('memory://' + this.imgName) + .backgroundImageSize(ImageSize.Cover) + + Column() + .width(this.FULL_PERCENT) + .height(this.FULL_PERCENT) + .backgroundColor(Color.White) + .opacity(0.9) + + Row() { + Column() { + Row() + .width(128) + .height(128) + .borderRadius(64) + .margin(8) + .shadow({ radius: 2, color: Color.Gray }) + .backgroundImage('memory://' + this.imgName) + .backgroundImageSize(ImageSize.Cover) + .onClick(() => { + postCardAction(this, { + action: this.ACTION_TYPE, + abilityName: this.ABILITY_NAME, + }); + }) + } + .justifyContent(FlexAlign.Center) + .height(this.FULL_PERCENT) + + Column() { + Row() { + Column() { + Text(this.audioItem.title) + .fontSize(32) + .fontColor($r('app.color.information_title_font')) + .fontWeight(FontWeight.Medium) + .maxLines(this.MAX_LINES_VALUE) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + Text(this.audioItem.artist) + .fontSize(24) + .fontColor($r('app.color.item_text_font')) + .fontWeight(FontWeight.Regular) + .margin({ top: 4 }) + .maxLines(this.MAX_LINES_VALUE) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + } + .justifyContent(FlexAlign.SpaceEvenly) + .alignItems(HorizontalAlign.Start) + .margin({ left: 8, right: 8 }) + .width('80%') + .onClick(() => { + postCardAction(this, { + action: this.ACTION_TYPE, + abilityName: this.ABILITY_NAME, + }); + }) + + Image(this.audioItem.isFavor ? $r('app.media.heart_fill') : $r('app.media.heart')) + .width(48) + .height(48) + .onClick(() => { + this.onSetFavor() + }) + } + .alignItems(VerticalAlign.Top) + .justifyContent(FlexAlign.SpaceBetween) + .width(this.FULL_PERCENT) + + Row() { + Image(this.playMode === PLAY_MODE.REPEAT ? $r('app.media.repeat') : (this.playMode === PLAY_MODE.REPEAT1 ? $r('app.media.repeat_1') : $r('app.media.shuffle'))) + .width(64) + .height(64) + .padding(4) + .onClick(() => { + this.setPlayMode(); + }) + + Image($r('app.media.backward_end_fill')) + .width(64) + .height(64) + .padding(4) + .onClick(() => { + this.onPreviousClick() + }) + if (this.isPlaying === ServerConstants.PLAYER_STATE_PLAYING) { + Image($r('app.media.pause')) + .width(64) + .height(64) + .padding(8) + .onClick(() => { + this.onPauseClick(); + }) + .onAppear(() => { + if (this.audioItem.id !== '') { + if (this.downloadImgId === this.audioItem.id) { + return; + } + this.downloadImgId = this.audioItem.id; + postCardAction(this, { + action: 'message', + params: { + info: ServerConstants.SONG_IMAGE_URL + this.audioItem.id + } + }); + } + }) + } else { + Image($r('app.media.play_fill')) + .width(64) + .height(64) + .padding(4) + .onClick(() => { + this.onPlayClick(); + }) + } + + Image($r('app.media.forward_end_fill')) + .width(64) + .height(64) + .padding(4) + .onClick(() => { + this.onNextClick() + }) + + } + .justifyContent(FlexAlign.SpaceBetween) + .width(this.FULL_PERCENT) + } + .width('60%') + .height(this.FULL_PERCENT) + .justifyContent(FlexAlign.SpaceEvenly) + } + .width(this.FULL_PERCENT) + .justifyContent(FlexAlign.SpaceEvenly) + .displayPriority(this.DISPLAY_PRIORITY_TWO) + } + } + + setPlayMode(): void { + postCardAction(this, { + 'action': 'call', + 'abilityName': this.ABILITY_NAME, + 'params': { + 'method': 'playMode' + } + }); + console.info(TAG, 'postCardAction setPlayMode'); + } + + onPlayClick(): void { + postCardAction(this, { + 'action': 'call', + 'abilityName': this.ABILITY_NAME, + 'params': { + 'method': 'play' + } + }); + console.info(TAG, 'postCardAction onPlayClick'); + } + + onPauseClick(): void { + postCardAction(this, { + 'action': 'call', + 'abilityName': this.ABILITY_NAME, + 'params': { + 'method': 'pause' + } + }); + console.info(TAG, 'postCardAction onPauseClick'); + } + + onPreviousClick(): void { + postCardAction(this, { + 'action': 'call', + 'abilityName': this.ABILITY_NAME, + 'params': { + 'method': 'prev' + } + }); + } + + onNextClick(): void { + postCardAction(this, { + 'action': 'call', + 'abilityName': this.ABILITY_NAME, + 'params': { + 'method': 'next' + } + }); + } + + onSetFavor(): void { + postCardAction(this, { + 'action': 'call', + 'abilityName': this.ABILITY_NAME, + 'params': { + 'method': 'setFavor' + } + }); + } +} \ No newline at end of file diff --git a/scenario/MusicPlayerOnline/entry/src/main/module.json5 b/scenario/MusicPlayerOnline/entry/src/main/module.json5 index 465a29648..20bdc8542 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/module.json5 +++ b/scenario/MusicPlayerOnline/entry/src/main/module.json5 @@ -37,15 +37,31 @@ ] } ], - "requestPermissions":[ + "extensionAbilities": [ { - "name" : "ohos.permission.INTERNET", + "name": "EntryFormAbility", + "srcEntry": "./ets/entryformability/EntryFormAbility.ets", + "label": "$string:EntryFormAbility_label", + "description": "$string:EntryFormAbility_desc", + "type": "form", + "metadata": [ + { + "name": "ohos.extension.form", + "resource": "$profile:form_config" + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.INTERNET", "reason": "$string:EntryAbility_desc", "usedScene": { "abilities": [ - "EntryAbility" + "EntryAbility", + "EntryFormAbility" ], - "when":"inuse" + "when": "inuse" } }, { diff --git a/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/color.json b/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/color.json index 3c712962d..97aaf78a3 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/color.json +++ b/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/color.json @@ -3,6 +3,22 @@ { "name": "start_window_background", "value": "#FFFFFF" + }, + { + "name": "information_title_font", + "value": "#E6000000" + }, + { + "name": "title_font", + "value": "#E5FFFFFF" + }, + { + "name": "item_text_font", + "value": "#99000000" + }, + { + "name": "image_info_background", + "value": "#FFFFFF" } ] } \ No newline at end of file diff --git a/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/float.json b/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/float.json new file mode 100644 index 000000000..e3bc44020 --- /dev/null +++ b/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/float.json @@ -0,0 +1,40 @@ +{ + "float": [ + { + "name": "card_title_font_size", + "value": "14fp" + }, + { + "name": "item_font_size", + "value": "12fp" + }, + { + "name": "maximum_padding", + "value": "12vp" + }, + { + "name": "item_margin_top", + "value": "2vp" + }, + { + "name": "image_margin_bottom", + "value": "8vp" + }, + { + "name": "info_column_padding", + "value": "12vp" + }, + { + "name": "info_column_width", + "value": "106vp" + }, + { + "name": "info_column_height", + "value": "120vp" + }, + { + "name": "image_border_radius", + "value": "8vp" + } + ] +} diff --git a/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/string.json b/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/string.json index b901aa71c..c4bf3c885 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/string.json +++ b/scenario/MusicPlayerOnline/entry/src/main/resources/base/element/string.json @@ -43,6 +43,30 @@ { "name": "exit", "value": "退出" + }, + { + "name": "EntryFormAbility_desc", + "value": "form_description" + }, + { + "name": "EntryFormAbility_label", + "value": "form_label" + }, + { + "name": "widget_desc", + "value": "This is a service widget." + }, + { + "name": "widget_display_name", + "value": "widget" + }, + { + "name": "card_title", + "value": "Title" + }, + { + "name": "introduction", + "value": "Introduction" } ] } \ No newline at end of file diff --git a/scenario/MusicPlayerOnline/entry/src/main/resources/base/media/ic_widget.png b/scenario/MusicPlayerOnline/entry/src/main/resources/base/media/ic_widget.png new file mode 100644 index 0000000000000000000000000000000000000000..c13bb4d340435b2e8d8fd90660ffc9916e1f6d68 GIT binary patch literal 5831 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 literal 0 HcmV?d00001 diff --git a/scenario/MusicPlayerOnline/entry/src/main/resources/base/profile/form_config.json b/scenario/MusicPlayerOnline/entry/src/main/resources/base/profile/form_config.json new file mode 100644 index 000000000..1354d3b1d --- /dev/null +++ b/scenario/MusicPlayerOnline/entry/src/main/resources/base/profile/form_config.json @@ -0,0 +1,25 @@ +{ + "forms": [ + { + "name": "widget", + "displayName": "$string:widget_display_name", + "description": "$string:widget_desc", + "src": "./ets/widget/pages/WidgetCard.ets", + "uiSyntax": "arkts", + "window": { + "designWidth": 720, + "autoDesignWidth": true + }, + "colorMode": "auto", + "isDynamic": true, + "isDefault": true, + "updateEnabled": false, + "scheduledUpdateTime": "10:30", + "updateDuration": 1, + "defaultDimension": "2*4", + "supportDimensions": [ + "2*4" + ] + } + ] +} \ No newline at end of file diff --git a/scenario/MusicPlayerOnline/entry/src/main/resources/en_US/element/string.json b/scenario/MusicPlayerOnline/entry/src/main/resources/en_US/element/string.json index ac57a47fc..84f1d2dd6 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/resources/en_US/element/string.json +++ b/scenario/MusicPlayerOnline/entry/src/main/resources/en_US/element/string.json @@ -39,6 +39,30 @@ { "name": "exit", "value": "Exit" + }, + { + "name": "EntryFormAbility_desc", + "value": "form_description" + }, + { + "name": "EntryFormAbility_label", + "value": "form_label" + }, + { + "name": "widget_desc", + "value": "This is a service widget." + }, + { + "name": "widget_display_name", + "value": "widget" + }, + { + "name": "card_title", + "value": "Title" + }, + { + "name": "introduction", + "value": "Introduction" } ] } \ No newline at end of file diff --git a/scenario/MusicPlayerOnline/entry/src/main/resources/zh_CN/element/string.json b/scenario/MusicPlayerOnline/entry/src/main/resources/zh_CN/element/string.json index 37be2ffa4..7233afb32 100644 --- a/scenario/MusicPlayerOnline/entry/src/main/resources/zh_CN/element/string.json +++ b/scenario/MusicPlayerOnline/entry/src/main/resources/zh_CN/element/string.json @@ -39,6 +39,30 @@ { "name": "exit", "value": "退出" + }, + { + "name": "EntryFormAbility_desc", + "value": "form_description" + }, + { + "name": "EntryFormAbility_label", + "value": "form_label" + }, + { + "name": "widget_desc", + "value": "This is a service widget." + }, + { + "name": "widget_display_name", + "value": "widget" + }, + { + "name": "card_title", + "value": "Title" + }, + { + "name": "introduction", + "value": "Introduction" } ] } \ No newline at end of file -- Gitee