mirror of
https://gitee.com/openharmony/codelabs
synced 2024-11-27 00:20:53 +00:00
音乐播放器(ArkTS)Codelinetr整改
Signed-off-by: 13871184879 <452399386@qq.com>
This commit is contained in:
parent
0dc1b75973
commit
6302d1c88e
@ -23,13 +23,13 @@
|
||||
|
||||
### 软件要求
|
||||
|
||||
- [DevEco Studio](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/start-overview.md#%E5%B7%A5%E5%85%B7%E5%87%86%E5%A4%87)版本:DevEco Studio 3.1 Release及以上版本。
|
||||
- OpenHarmony SDK版本:API version 9及以上版本。
|
||||
- [DevEco Studio](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/quick-start/start-overview.md#%E5%B7%A5%E5%85%B7%E5%87%86%E5%A4%87)版本:DevEco Studio 3.1 Release。
|
||||
- OpenHarmony SDK版本:API version 9。
|
||||
|
||||
### 硬件要求
|
||||
|
||||
- 开发板类型:[润和RK3568开发板](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/quickstart-appendix-rk3568.md)。
|
||||
- OpenHarmony系统:3.2 Release及以上版本。
|
||||
- OpenHarmony系统:3.2 Release。
|
||||
|
||||
### 环境搭建
|
||||
|
||||
@ -56,15 +56,16 @@
|
||||
|
||||
```
|
||||
├──entry/src/main/ets // 代码区
|
||||
│ ├──common
|
||||
│ │ ├──bean
|
||||
│ │ │ └──MusicItem.ets // 音乐类
|
||||
│ ├──common
|
||||
│ │ ├──constants
|
||||
│ │ │ └──CommonConstants.ets // 公共常量
|
||||
│ │ ├──model
|
||||
│ │ │ └──PlayBarModel // 播放栏数据模型
|
||||
│ │ └──utils
|
||||
│ │ ├──AvSessionUtil.ets // 媒体会话工具类
|
||||
│ │ ├──BackgroundTaskUtil.ets // 后台任务工具类
|
||||
│ │ ├──CommonUtil.ets // 公共工具类
|
||||
│ │ ├──GlobalContext.ets // 公共工具类
|
||||
│ │ ├──Logger.ets // 日志类
|
||||
│ │ └──ResourceManagerUtil.ets // 资源管理工具类
|
||||
│ ├──controller
|
||||
@ -84,6 +85,7 @@
|
||||
│ │ ├──PlayListMusicView.ets // 弹窗音乐模块
|
||||
│ │ └──ProgressView.ets // 播放页
|
||||
│ └──viewmodel
|
||||
│ ├──MusicItem.ets // 音乐类
|
||||
│ └──MusicViewModel.ets // 歌单音乐模型
|
||||
└──entry/src/main/resources // 应用资源目录
|
||||
```
|
||||
@ -100,22 +102,16 @@
|
||||
|
||||
```typescript
|
||||
// AudioPlayerController.ets
|
||||
import media from '@ohos.multimedia.media';
|
||||
...
|
||||
export class AudioPlayerController {
|
||||
...
|
||||
initAudioPlayer() {
|
||||
media.createAVPlayer((error, video) => {
|
||||
if (CommonUtil.isEmpty(video)) {
|
||||
this.avPlayer = video;
|
||||
Logger.error(TAG, `createAVPlayer fail, error: ${error}`);
|
||||
} else {
|
||||
this.avPlayer = video;
|
||||
Logger.info(TAG, 'createAVPlayer success');
|
||||
}
|
||||
});
|
||||
}
|
||||
...
|
||||
initAudioPlayer() {
|
||||
media.createAVPlayer((error, video) => {
|
||||
if (video === undefined) {
|
||||
this.avPlayer = video;
|
||||
Logger.error(TAG, `createAVPlayer fail, error: ${error}`);
|
||||
} else {
|
||||
this.avPlayer = video;
|
||||
Logger.info(TAG, 'createAVPlayer success');
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
@ -124,75 +120,94 @@ export class AudioPlayerController {
|
||||
```typescript
|
||||
// AudioPlayerController.ets
|
||||
// 注册AVPlayer回调函数
|
||||
setEventCallBack(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
Logger.info(TAG, 'setEventCallBack fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
// 状态变更回调函数
|
||||
setEventCallBack() {
|
||||
...
|
||||
// 状态变更回调函数。
|
||||
this.avPlayer.on('stateChange', async (state) => {
|
||||
...
|
||||
switch (state) {
|
||||
case StateEvent.IDLE: // 调用reset成功后触发此状态。
|
||||
...
|
||||
break;
|
||||
case StateEvent.INITIALIZED: // 设置播放源触发此状态。
|
||||
...
|
||||
break;
|
||||
case StateEvent.PREPARED:
|
||||
...
|
||||
break;
|
||||
case StateEvent.PLAYING:
|
||||
...
|
||||
break;
|
||||
case StateEvent.COMPLETED:
|
||||
...
|
||||
break;
|
||||
default:
|
||||
Logger.error('unknown state: ' + state);
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
设置音频资源,AVPlayer进入initialized状态。在initialized状态回调中,调用prepare方法,准备播放,AVPlayer进入prepared状态。
|
||||
|
||||
```typescript
|
||||
// AudioPlayerController.ets
|
||||
// 设置播放源
|
||||
this.avPlayer.fdSrc = src;
|
||||
...
|
||||
// 设置播放源后进入initialized状态
|
||||
case stateEvent.INITIALIZED:
|
||||
Logger.info(TAG, 'state initialized called');
|
||||
this.avPlayerState = playerState.INITIALIZED;
|
||||
this.avPlayer.prepare().then(() => {
|
||||
Logger.info(TAG, 'prepare success');
|
||||
}, (err) => {
|
||||
Logger.error(TAG, 'prepare failed,error message is: ' + err.message);
|
||||
async play(src: media.AVFileDescriptor, seekTo: number) {
|
||||
Logger.info(TAG, 'audioPlayer play');
|
||||
...
|
||||
// 设置播放源
|
||||
this.avPlayer.fdSrc = src;
|
||||
}
|
||||
|
||||
setEventCallBack() {
|
||||
...
|
||||
this.avPlayer.on('stateChange', async (state) => {
|
||||
...
|
||||
switch (state) {
|
||||
...
|
||||
case StateEvent.INITIALIZED:// 设置播放源后进入initialized状态
|
||||
Logger.info(TAG, 'state initialized called');
|
||||
this.avPlayerState = PlayerState.INITIALIZED;
|
||||
this.avPlayer.prepare().then(() => {
|
||||
Logger.info(TAG, 'prepare success');
|
||||
}, (err) => {
|
||||
Logger.error(TAG, `prepare failed,error message is: ${err.message}`);
|
||||
})
|
||||
break;
|
||||
...
|
||||
}
|
||||
})
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
AVPlayer进入prepared状态,可进行音频播控操作。包括播放play\(\)、跳转至指定位置播放seek\(\)、暂停pause\(\)、停止stop\(\)等操作。
|
||||
|
||||
```typescript
|
||||
// AudioPlayerController.ets
|
||||
case stateEvent.PREPARED:
|
||||
Logger.info(TAG, 'state prepared called');
|
||||
this.avPlayer.play();
|
||||
break;
|
||||
setEventCallBack() {
|
||||
...
|
||||
this.avPlayer.on('stateChange', async (state) => {
|
||||
...
|
||||
switch (state) {
|
||||
...
|
||||
case StateEvent.PREPARED:
|
||||
Logger.info(TAG, 'state prepared called');
|
||||
this.avPlayer.play();
|
||||
break;
|
||||
...
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
切换歌曲播放时,需调用reset\(\)重置资源。此时AVPlayer重新进入idle状态,允许更换资源。
|
||||
|
||||
```typescript
|
||||
// AudioPlayerController.ets
|
||||
if (this.avPlayerState === playerState.INITIALIZED) {
|
||||
await this.avPlayer.reset();
|
||||
Logger.info(TAG, 'play reset success');
|
||||
async play(src: media.AVFileDescriptor, seekTo: number) {
|
||||
...
|
||||
if (this.avPlayerState === PlayerState.INITIALIZED) {
|
||||
await this.avPlayer.reset();
|
||||
Logger.info(TAG, 'play reset success');
|
||||
}
|
||||
...
|
||||
}
|
||||
this.avPlayer.fdSrc = src;
|
||||
```
|
||||
|
||||
>![](public_sys-resources/icon-note.gif) **说明:**
|
||||
@ -249,8 +264,10 @@ async release() {
|
||||
import wantAgent from '@ohos.app.ability.wantAgent';
|
||||
import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
|
||||
...
|
||||
public static startContinuousTask(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
export class BackgroundTaskUtil {
|
||||
...
|
||||
public static startContinuousTask(context: Context) {
|
||||
if (context === undefined) {
|
||||
Logger.info(TAG, 'startContinuousTask fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
@ -266,7 +283,7 @@ import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager'
|
||||
operationType: wantAgent.OperationType.START_ABILITY,
|
||||
// 用户定义的私有属性
|
||||
requestCode: CommonConstants.BACKGROUND_REQUEST_CODE
|
||||
};
|
||||
} as wantAgent.WantAgentInfo;
|
||||
|
||||
// 通过WanAgent模块的方法获取WanAgent对象
|
||||
wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => {
|
||||
@ -274,15 +291,16 @@ import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager'
|
||||
backgroundTaskManager.startBackgroundRunning(context, backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
|
||||
wantAgentObj).then(() => {
|
||||
Logger.info(TAG, 'startBackgroundRunning succeeded');
|
||||
}).catch((err) => {
|
||||
Logger.error(TAG, 'startBackgroundRunning failed Cause: ' + JSON.stringify(err));
|
||||
}).catch((err: Error) => {
|
||||
Logger.error(TAG, 'startBackgroundRunning failed, Cause: ' + JSON.stringify(err));
|
||||
});
|
||||
} catch (error) {
|
||||
Logger.error(TAG, `startBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
...
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
暂停音乐播放,结束长时任务。
|
||||
@ -292,22 +310,24 @@ import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager'
|
||||
import wantAgent from '@ohos.app.ability.wantAgent';
|
||||
import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
|
||||
...
|
||||
public static stopContinuousTask(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
export class BackgroundTaskUtil {
|
||||
...
|
||||
public static stopContinuousTask(context: Context) {
|
||||
if (context === undefined) {
|
||||
Logger.info(TAG, 'stopContinuousTask fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
backgroundTaskManager.stopBackgroundRunning(context).then(() => {
|
||||
Logger.info(TAG, 'stopBackgroundRunning succeeded');
|
||||
}).catch((err) => {
|
||||
}).catch((err: Error) => {
|
||||
Logger.error(TAG, 'stopBackgroundRunning failed Cause: ' + JSON.stringify(err));
|
||||
});
|
||||
} catch (error) {
|
||||
Logger.error(TAG, `stopBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## 总结
|
||||
|
@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import resourceManager from '@ohos.resourceManager';
|
||||
|
||||
/**
|
||||
* Song Attributes.
|
||||
*/
|
||||
export interface MusicItemProperties {
|
||||
/**
|
||||
* Identifier.
|
||||
*/
|
||||
id: number;
|
||||
|
||||
/**
|
||||
* Music name.
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Singer.
|
||||
*/
|
||||
singer: string;
|
||||
|
||||
/**
|
||||
* Lyricist.
|
||||
*/
|
||||
lyrics: string;
|
||||
|
||||
/**
|
||||
* Resource Path.
|
||||
*/
|
||||
path: string;
|
||||
|
||||
/**
|
||||
* Member song or not.
|
||||
*/
|
||||
isVip: boolean;
|
||||
|
||||
/**
|
||||
* Song icon.
|
||||
*/
|
||||
image: Resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Song entity class.
|
||||
*/
|
||||
export class MusicItem {
|
||||
/**
|
||||
* Identifier.
|
||||
*/
|
||||
id: number;
|
||||
|
||||
/**
|
||||
* Music name.
|
||||
*/
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Singer.
|
||||
*/
|
||||
singer: string;
|
||||
|
||||
/**
|
||||
* Lyricist.
|
||||
*/
|
||||
lyrics: string;
|
||||
|
||||
/**
|
||||
* Resource Path.
|
||||
*/
|
||||
path: string;
|
||||
|
||||
/**
|
||||
* Member song or not.
|
||||
*/
|
||||
isVip: boolean;
|
||||
|
||||
/**
|
||||
* Song icon.
|
||||
*/
|
||||
image: Resource;
|
||||
|
||||
/**
|
||||
* Resource descriptor.
|
||||
*/
|
||||
rawFileDescriptor: resourceManager.RawFileDescriptor;
|
||||
|
||||
constructor(musicItemProperties: MusicItemProperties, rawFileDescriptor: resourceManager.RawFileDescriptor) {
|
||||
this.id = musicItemProperties.id;
|
||||
this.name = musicItemProperties.name;
|
||||
this.singer = musicItemProperties.singer;
|
||||
this.lyrics = musicItemProperties.lyrics;
|
||||
this.path = musicItemProperties.path;
|
||||
this.isVip = musicItemProperties.isVip;
|
||||
this.image = musicItemProperties.image;
|
||||
this.rawFileDescriptor = rawFileDescriptor;
|
||||
}
|
||||
}
|
@ -21,203 +21,159 @@ export class CommonConstants {
|
||||
* FontWeight bolder.
|
||||
*/
|
||||
static readonly FONT_WEIGHT_BOLDER: number = 500;
|
||||
|
||||
/**
|
||||
* Weight of 100%.
|
||||
*/
|
||||
static readonly FULL_WIDTH: string = '100%';
|
||||
|
||||
/**
|
||||
* Height of 100%.
|
||||
*/
|
||||
static readonly FULL_HEIGHT: string = '100%';
|
||||
|
||||
/**
|
||||
* Music list page.
|
||||
*/
|
||||
static readonly PAGE_MUSIC_LIST: string = 'pages/MusicList';
|
||||
|
||||
/**
|
||||
* Play page.
|
||||
*/
|
||||
static readonly PAGE_PLAY: string = 'pages/Play';
|
||||
|
||||
/**
|
||||
* Start up delayTime.
|
||||
*/
|
||||
static readonly DELAY_TIME: number = 1000;
|
||||
|
||||
/**
|
||||
* Start position.
|
||||
*/
|
||||
static readonly START_POSITION: number = 0;
|
||||
|
||||
/**
|
||||
* Total value.
|
||||
*/
|
||||
static readonly TOTAL_VALUE: number = 100;
|
||||
|
||||
/**
|
||||
* Divider color.
|
||||
*/
|
||||
static readonly DIVIDER_COLOR: number = 0x33000000;
|
||||
|
||||
/**
|
||||
* Start up page const.
|
||||
*/
|
||||
static readonly START_UP_PAGE = {
|
||||
IMAGE_WIDTH: '53.3%',
|
||||
IMAGE_HEIGHT: '24.6%',
|
||||
IMAGE_CONTAINER: '75.5%'
|
||||
}
|
||||
|
||||
static readonly START_IMAGE_WIDTH: string = '53.3%';
|
||||
static readonly START_IMAGE_HEIGHT: string = '24.6%';
|
||||
static readonly START_IMAGE_CONTAINER: string = '75.5%';
|
||||
/**
|
||||
* Music list page const.
|
||||
*/
|
||||
static readonly MUSIC_LIST_PAGE = {
|
||||
TEXT_MARGIN_LEFT: '6.7%',
|
||||
TEXT_MARGIN_RIGHT: '6.7%',
|
||||
TEXT_MARGIN_TOP: '1.5%',
|
||||
TEXT_MARGIN_BOTTOM: '1.5%',
|
||||
TEXT_WIDTH: '86.7%',
|
||||
TEXT_HEIGHT: '6.7%'
|
||||
}
|
||||
|
||||
static readonly TEXT_MARGIN_LEFT: string = '6.7%';
|
||||
static readonly TEXT_MARGIN_RIGHT: string = '6.7%';
|
||||
static readonly TEXT_MARGIN_TOP: string = '1.5%';
|
||||
static readonly TEXT_MARGIN_BOTTOM: string = '1.5%';
|
||||
static readonly TEXT_WIDTH: string = '86.7%';
|
||||
static readonly TEXT_HEIGHT: string = '6.7%';
|
||||
/**
|
||||
* Play page const.
|
||||
*/
|
||||
static readonly PLAY_PAGE = {
|
||||
NAVIGATOR_WIDTH: '6.7%',
|
||||
NAVIGATOR_HEIGHT: '3.1%',
|
||||
LAYOUT_WEIGHT: 1,
|
||||
NAVIGATOR_PADDING_LEFT: '6.7%',
|
||||
NAVIGATOR_PADDING_RIGHT: '6.7%',
|
||||
NAVIGATOR_PADDING_TOP: '1.9%',
|
||||
NAVIGATOR_PADDING_BOTTOM: '1.9%',
|
||||
CONTROL_WIDTH: '81.2%'
|
||||
}
|
||||
|
||||
static readonly NAVIGATOR_WIDTH: string = '6.7%';
|
||||
static readonly NAVIGATOR_HEIGHT: string = '3.1%';
|
||||
static readonly LAYOUT_WEIGHT: number = 1;
|
||||
static readonly NAVIGATOR_PADDING_LEFT: string = '6.7%';
|
||||
static readonly NAVIGATOR_PADDING_RIGHT: string = '6.7%';
|
||||
static readonly NAVIGATOR_PADDING_TOP: string = '1.9%';
|
||||
static readonly NAVIGATOR_PADDING_BOTTOM: string = '1.9%';
|
||||
static readonly CONTROL_WIDTH: string = '81.2%';
|
||||
/**
|
||||
* Control view const.
|
||||
*/
|
||||
static readonly CONTROL_VIEW = {
|
||||
MODE_ICON_WIDTH: '7.5%',
|
||||
MODE_ICON_HEIGHT: '3.1%',
|
||||
MODE_ICON_MARGIN_RIGHT: '12%',
|
||||
PREVIOUS_WIDTH: '8.3%',
|
||||
PREVIOUS_HEIGHT: '3.8%',
|
||||
PREVIOUS_MARGIN_RIGHT: '9%',
|
||||
STATE_ICON_WIDTH: '18.9%',
|
||||
STATE_ICON_HEIGHT: '8.7%',
|
||||
STATE_ICON_MARGIN_RIGHT: '9%',
|
||||
NEXT_WIDTH: '8.3%',
|
||||
NEXT_HEIGHT: '3.8%',
|
||||
NEXT_MARGIN_RIGHT: '12%',
|
||||
PLAY_LIST_WIDTH: '7.5%',
|
||||
PLAY_LIST_HEIGHT: '3.1%',
|
||||
PAGE_MARGIN_TOP: '4.6%'
|
||||
}
|
||||
|
||||
static readonly MODE_ICON_WIDTH: string = '7.5%';
|
||||
static readonly MODE_ICON_HEIGHT: string = '3.1%';
|
||||
static readonly MODE_ICON_MARGIN_RIGHT: string = '12%';
|
||||
static readonly PREVIOUS_WIDTH: string = '8.3%';
|
||||
static readonly PREVIOUS_HEIGHT: string = '3.8%';
|
||||
static readonly PREVIOUS_MARGIN_RIGHT: string = '9%';
|
||||
static readonly STATE_ICON_WIDTH: string = '18.9%';
|
||||
static readonly STATE_ICON_HEIGHT: string = '8.7%';
|
||||
static readonly STATE_ICON_MARGIN_RIGHT: string = '9%';
|
||||
static readonly NEXT_WIDTH: string = '8.3%';
|
||||
static readonly NEXT_HEIGHT: string = '3.8%';
|
||||
static readonly NEXT_MARGIN_RIGHT: string = '12%';
|
||||
static readonly PLAY_LIST_WIDTH: string = '7.5%';
|
||||
static readonly PLAY_LIST_HEIGHT: string = '3.1%';
|
||||
static readonly PAGE_MARGIN_TOP: string = '4.6%';
|
||||
/**
|
||||
* Music card view const.
|
||||
*/
|
||||
static readonly MUSIC_CARD_VIEW = {
|
||||
IMAGE_HEIGHT: '41.7%',
|
||||
NAME_MARGIN_TOP: '3.1%',
|
||||
SINGER_MARGIN_TOP: '1.5%',
|
||||
LYRICS_MARGIN_TOP: '1%'
|
||||
}
|
||||
|
||||
static readonly IMAGE_HEIGHT: string = '41.7%';
|
||||
static readonly NAME_MARGIN_TOP: string = '3.1%';
|
||||
static readonly SINGER_MARGIN_TOP: string = '1.5%';
|
||||
static readonly LYRICS_MARGIN_TOP: string = '1%';
|
||||
/**
|
||||
* Music view const.
|
||||
*/
|
||||
static readonly MUSIC_VIEW = {
|
||||
IMAGE_WIDTH: '17.8%',
|
||||
IMAGE_HEIGHT: '8.2%',
|
||||
ROW_MARGIN_LEFT: '4.4%',
|
||||
PAGE_MARGIN_LEFT: '3%',
|
||||
PAGE_MARGIN_TOP: '1.5%',
|
||||
PAGE_MARGIN_RIGHT: '3%',
|
||||
PAGE_MARGIN_BUTTON: '1.5%'
|
||||
}
|
||||
|
||||
static readonly IMAGE_WIDTH: string = '17.8%';
|
||||
static readonly MUSIC_IMAGE_HEIGHT: string = '8.2%';
|
||||
static readonly ROW_MARGIN_LEFT: string = '4.4%';
|
||||
static readonly PAGE_MARGIN_LEFT: string = '3%';
|
||||
static readonly MUSIC_MARGIN_TOP: string = '1.5%';
|
||||
static readonly PAGE_MARGIN_RIGHT: string = '3%';
|
||||
static readonly PAGE_MARGIN_BUTTON: string = '1.5%';
|
||||
/**
|
||||
* List dialog const.
|
||||
*/
|
||||
static readonly LIST_DIALOG = {
|
||||
IMAGE_WIDTH: '6.7%',
|
||||
IMAGE_HEIGHT: '3.1%',
|
||||
IMAGE_MARGIN_RIGHT: '3.3%',
|
||||
ROW_WIDTH: '90%',
|
||||
ROW_MARGIN_TOP: '3%',
|
||||
ROW_MARGIN_BOTTOM: '3%',
|
||||
LIST_WIDTH: '90%',
|
||||
LIST_HEIGHT: '57.4%',
|
||||
PAGE_MARGIN_LEFT: '3.3%',
|
||||
LIST_SPACE: 10,
|
||||
LIST_INITIAL_INDEX: 0,
|
||||
DIVIDER_STROKE_WIDTH: 1,
|
||||
DIVIDER_START_MARGIN: 0,
|
||||
END_MARGIN: 20
|
||||
}
|
||||
|
||||
static readonly DIALOG_IMAGE_WIDTH: string = '6.7%';
|
||||
static readonly DIALOG_IMAGE_HEIGHT: string = '3.1%';
|
||||
static readonly IMAGE_MARGIN_RIGHT: string = '3.3%';
|
||||
static readonly ROW_WIDTH: string = '90%';
|
||||
static readonly ROW_MARGIN_TOP: string = '3%';
|
||||
static readonly ROW_MARGIN_BOTTOM: string = '3%';
|
||||
static readonly LIST_WIDTH: string = '90%';
|
||||
static readonly LIST_HEIGHT: string = '57.4%';
|
||||
static readonly DIALOG_MARGIN_LEFT: string = '3.3%';
|
||||
static readonly LIST_SPACE: number = 10;
|
||||
static readonly LIST_INITIAL_INDEX: number = 0;
|
||||
static readonly DIVIDER_STROKE_WIDTH: number = 1;
|
||||
static readonly DIVIDER_START_MARGIN: number = 0;
|
||||
static readonly END_MARGIN: number = 20;
|
||||
/**
|
||||
* List dialog music.
|
||||
*/
|
||||
static readonly LIST_DIALOG_MUSIC = {
|
||||
IMAGE_WIDTH: '4.4%',
|
||||
IMAGE_HEIGHT: '2.1%',
|
||||
IMAGE_MARGIN_RIGHT: '2.1%',
|
||||
LINE_HEIGHT: 21,
|
||||
MUSIC_MARGIN_TOP: '1.7%',
|
||||
MUSIC_MARGIN_BOTTOM: '1.7%'
|
||||
}
|
||||
|
||||
static readonly LIST_IMAGE_WIDTH: string = '4.4%';
|
||||
static readonly LIST_IMAGE_HEIGHT: string = '2.1%';
|
||||
static readonly LIST_MARGIN_RIGHT: string = '2.1%';
|
||||
static readonly LINE_HEIGHT: number = 21;
|
||||
static readonly LIST_MARGIN_TOP: string = '1.7%';
|
||||
static readonly MUSIC_MARGIN_BOTTOM: string = '1.7%';
|
||||
/**
|
||||
* Progress view const.
|
||||
*/
|
||||
static readonly PROGRESS_VIEW = {
|
||||
TEXT_MARGIN_RIGHT: '3.3%',
|
||||
TEXT_MARGIN_LEFT: '3.3%',
|
||||
VIEW_MARGIN_TOP: '8.2%',
|
||||
PROGRESS_MIN: 0
|
||||
}
|
||||
|
||||
static readonly PROGRESS_MARGIN_RIGHT: string = '3.3%';
|
||||
static readonly PROGRESS_MARGIN_LEFT: string = '3.3%';
|
||||
static readonly VIEW_MARGIN_TOP: string = '8.2%';
|
||||
static readonly PROGRESS_MIN: number = 0;
|
||||
/**
|
||||
* BackgroundTask parameter.
|
||||
*/
|
||||
static readonly BACKGROUND_REQUEST_CODE: number = 0;
|
||||
|
||||
/**
|
||||
* Const of commonUtil.
|
||||
*/
|
||||
static readonly COMMON_UTIL = {
|
||||
SECOND_PRECISION: 0,
|
||||
SECOND_TO_MS: 1000,
|
||||
MIN_TO_SEC: 60,
|
||||
MAX_OF_INDIVIDUAL: 9
|
||||
}
|
||||
|
||||
static readonly SECOND_PRECISION: number = 0;
|
||||
static readonly SECOND_TO_MS: number = 1000;
|
||||
static readonly MIN_TO_SEC: number = 60;
|
||||
static readonly MAX_OF_INDIVIDUAL: number = 9;
|
||||
/**
|
||||
* Default id.
|
||||
*/
|
||||
static readonly DEFAULT_TIME_ID: number = -1;
|
||||
|
||||
/**
|
||||
* Number of modes.
|
||||
*/
|
||||
static readonly MODE_QUANTITY: number = 3;
|
||||
|
||||
/**
|
||||
* Number of musics.
|
||||
*/
|
||||
static readonly MUSICS_QUANTITY: number = 6;
|
||||
|
||||
/**
|
||||
* Bundle name.
|
||||
*/
|
||||
static readonly BUNDLE_NAME: string = 'com.example.audioplayer';
|
||||
|
||||
/**
|
||||
* Ability name.
|
||||
*/
|
||||
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { MusicItem } from '../../viewmodel/MusicItem';
|
||||
import { CommonConstants, PlayMode, PlayState } from '../constants/CommonConstants';
|
||||
|
||||
@Observed
|
||||
export class PlayBarModel {
|
||||
playValue: number = CommonConstants.START_POSITION;
|
||||
playMode: number = PlayMode.LIST_LOOP;
|
||||
playStateIcon: Resource = $r('app.media.ic_play');
|
||||
playModeIcon: Resource = $r('app.media.ic_list_mode');
|
||||
totalValue: number = CommonConstants.TOTAL_VALUE;
|
||||
musicItem?: MusicItem;
|
||||
playState: number = PlayState.PLAY;
|
||||
}
|
@ -14,8 +14,10 @@
|
||||
*/
|
||||
|
||||
import avSession from '@ohos.multimedia.avsession';
|
||||
import { AudioPlayerController } from '../../controller/AudioPlayerControllerl';
|
||||
import { PlayBarModel } from '../model/PlayBarModel';
|
||||
import Logger from '../utils/Logger';
|
||||
import { CommonUtil } from './CommonUtil';
|
||||
import { GlobalContext } from './GlobalContext';
|
||||
|
||||
const TAG = '[AvSessionUtil]';
|
||||
|
||||
@ -23,43 +25,41 @@ const TAG = '[AvSessionUtil]';
|
||||
* Media session tool class.
|
||||
*/
|
||||
export class AvSessionUtil {
|
||||
|
||||
/**
|
||||
* Initializing the playback control center.
|
||||
*
|
||||
* @param context Context.
|
||||
*/
|
||||
public static initAvSession(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
Logger.error(TAG, 'initAvSession fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
return new Promise(async () => {
|
||||
public static initAvSession(playBarModel: PlayBarModel) {
|
||||
return new Promise<string>(async () => {
|
||||
try {
|
||||
// Sets the current music metadata.
|
||||
let metadata = {
|
||||
assetId: context.musicItem.id.toString(),
|
||||
title: context.musicItem.name,
|
||||
artist: context.musicItem.singer
|
||||
};
|
||||
await globalThis.currentSession.setAVMetadata(metadata);
|
||||
assetId: playBarModel!.musicItem!.id.toString(),
|
||||
title: playBarModel!.musicItem!.name,
|
||||
artist: playBarModel!.musicItem!.singer
|
||||
} as avSession.AVMetadata;
|
||||
let currentSession = GlobalContext.getContext().getObject('currentSession') as avSession.AVSession;
|
||||
await currentSession.setAVMetadata(metadata);
|
||||
|
||||
// Set the playback status and give an initial status.
|
||||
AvSessionUtil.setAVPlayState(avSession.PlaybackState.PLAYBACK_STATE_PLAY);
|
||||
|
||||
// The following are all callback listeners. Currently, only the playback and pause functions are implemented.
|
||||
globalThis.currentSession.on('play', () => {
|
||||
currentSession.on('play', () => {
|
||||
Logger.info(TAG, 'Invoke the playback method of avSession.');
|
||||
globalThis.AudioPlayerController.play(context.musicItem.rawFileDescriptor, context.playValue);
|
||||
context.playStateIcon = $r('app.media.ic_play');
|
||||
let playController = GlobalContext.getContext().getObject('audioPlayerController') as AudioPlayerController;
|
||||
playController.play(playBarModel!.musicItem!.rawFileDescriptor, playBarModel.playValue);
|
||||
playBarModel.playStateIcon = $r('app.media.ic_play');
|
||||
AvSessionUtil.setAVPlayState(avSession.PlaybackState.PLAYBACK_STATE_PLAY);
|
||||
});
|
||||
|
||||
// Registering and suspending command listening.
|
||||
globalThis.currentSession.on('pause', () => {
|
||||
currentSession.on('pause', () => {
|
||||
Logger.info(TAG, 'Invoke the pause method of avSession.');
|
||||
globalThis.AudioPlayerController.pause();
|
||||
context.playStateIcon = $r('app.media.ic_pause');
|
||||
let playController = GlobalContext.getContext().getObject('audioPlayerController') as AudioPlayerController;
|
||||
playController.pause();
|
||||
playBarModel.playStateIcon = $r('app.media.ic_pause');
|
||||
AvSessionUtil.setAVPlayState(avSession.PlaybackState.PLAYBACK_STATE_PAUSE);
|
||||
});
|
||||
}
|
||||
@ -74,17 +74,18 @@ export class AvSessionUtil {
|
||||
*
|
||||
* @param state Status of the Playback Control Center.
|
||||
*/
|
||||
public static setAVPlayState(state:avSession.PlaybackState) {
|
||||
if (CommonUtil.isEmpty(state)) {
|
||||
public static setAVPlayState(state: avSession.PlaybackState) {
|
||||
if (state === undefined) {
|
||||
Logger.info(TAG, 'setAVPlayState fail,state is empty.');
|
||||
return;
|
||||
}
|
||||
globalThis.currentSession.setAVPlaybackState({ state: state })
|
||||
let currentSession = GlobalContext.getContext().getObject('currentSession') as avSession.AVSession;
|
||||
currentSession.setAVPlaybackState({ state: state })
|
||||
.then(() => {
|
||||
Logger.info(TAG, 'setAVPlaybackState successfully');
|
||||
})
|
||||
.catch((err) => {
|
||||
Logger.info(TAG, `setAVPlaybackState : ERROR : ${err.message}`);
|
||||
.catch((err: Error) => {
|
||||
Logger.info(TAG, `setAVPlaybackState : ERROR : ${err}`);
|
||||
});
|
||||
}
|
||||
|
||||
@ -93,16 +94,13 @@ export class AvSessionUtil {
|
||||
*
|
||||
* @param context Context.
|
||||
*/
|
||||
public static setAVMetadata(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
Logger.error(TAG, 'setAVMetadata fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
public static setAVMetadata(playBarModel: PlayBarModel) {
|
||||
let metadata = {
|
||||
assetId: context.musicItem.id.toString(),
|
||||
title: context.musicItem.name,
|
||||
artist: context.musicItem.singer
|
||||
};
|
||||
globalThis.currentSession.setAVMetadata(metadata);
|
||||
assetId: playBarModel!.musicItem!.id.toString(),
|
||||
title: playBarModel!.musicItem!.name,
|
||||
artist: playBarModel!.musicItem!.singer
|
||||
} as avSession.AVMetadata;
|
||||
let currentSession = GlobalContext.getContext().getObject('currentSession') as avSession.AVSession;
|
||||
currentSession.setAVMetadata(metadata);
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@ import wantAgent from '@ohos.app.ability.wantAgent';
|
||||
import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
|
||||
import { CommonConstants } from '../constants/CommonConstants';
|
||||
import Logger from '../utils/Logger';
|
||||
import { CommonUtil } from './CommonUtil';
|
||||
|
||||
const TAG = '[BackgroundTaskUtil]';
|
||||
|
||||
@ -25,14 +24,13 @@ const TAG = '[BackgroundTaskUtil]';
|
||||
* Background task tool class.
|
||||
*/
|
||||
export class BackgroundTaskUtil {
|
||||
|
||||
/**
|
||||
* Start a long-time task in the background.
|
||||
*
|
||||
* @param context Context.
|
||||
*/
|
||||
public static startContinuousTask(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
public static startContinuousTask(context: Context) {
|
||||
if (context === undefined) {
|
||||
Logger.info(TAG, 'startContinuousTask fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
@ -48,7 +46,7 @@ export class BackgroundTaskUtil {
|
||||
operationType: wantAgent.OperationType.START_ABILITY,
|
||||
// A private value defined by the user.
|
||||
requestCode: CommonConstants.BACKGROUND_REQUEST_CODE
|
||||
};
|
||||
} as wantAgent.WantAgentInfo;
|
||||
|
||||
// Obtain the WantAgent object by using the method of the wantAgent module.
|
||||
wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => {
|
||||
@ -56,8 +54,8 @@ export class BackgroundTaskUtil {
|
||||
backgroundTaskManager.startBackgroundRunning(context, backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
|
||||
wantAgentObj).then(() => {
|
||||
Logger.info(TAG, 'startBackgroundRunning succeeded');
|
||||
}).catch((err) => {
|
||||
Logger.error(TAG, 'startBackgroundRunning failed Cause: ' + JSON.stringify(err));
|
||||
}).catch((err: Error) => {
|
||||
Logger.error(TAG, 'startBackgroundRunning failed, Cause: ' + JSON.stringify(err));
|
||||
});
|
||||
} catch (error) {
|
||||
Logger.error(TAG, `startBackgroundRunning failed. code is ${error.code} message is ${error.message}`);
|
||||
@ -70,15 +68,15 @@ export class BackgroundTaskUtil {
|
||||
*
|
||||
* @param context context.
|
||||
*/
|
||||
public static stopContinuousTask(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
public static stopContinuousTask(context: Context) {
|
||||
if (context === undefined) {
|
||||
Logger.info(TAG, 'stopContinuousTask fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
backgroundTaskManager.stopBackgroundRunning(context).then(() => {
|
||||
Logger.info(TAG, 'stopBackgroundRunning succeeded');
|
||||
}).catch((err) => {
|
||||
}).catch((err: Error) => {
|
||||
Logger.error(TAG, 'stopBackgroundRunning failed Cause: ' + JSON.stringify(err));
|
||||
});
|
||||
} catch (error) {
|
||||
|
@ -29,12 +29,12 @@ export class CommonUtil {
|
||||
if (ms < 0) {
|
||||
ms = 0;
|
||||
}
|
||||
const secondPrecision = CommonConstants.COMMON_UTIL.SECOND_PRECISION;
|
||||
const secondDuration = ms / CommonConstants.COMMON_UTIL.SECOND_TO_MS;
|
||||
let min = Math.floor(secondDuration / CommonConstants.COMMON_UTIL.MIN_TO_SEC);
|
||||
let sec = Math.round(secondDuration - min * CommonConstants.COMMON_UTIL.MIN_TO_SEC);
|
||||
const secondPrecision = CommonConstants.SECOND_PRECISION;
|
||||
const secondDuration = ms / CommonConstants.SECOND_TO_MS;
|
||||
let min = Math.floor(secondDuration / CommonConstants.MIN_TO_SEC);
|
||||
let sec = Math.round(secondDuration - min * CommonConstants.MIN_TO_SEC);
|
||||
let secStr = sec.toFixed(secondPrecision);
|
||||
if (parseInt(secStr) <= CommonConstants.COMMON_UTIL.MAX_OF_INDIVIDUAL) {
|
||||
if (Number.parseInt(secStr) <= CommonConstants.MAX_OF_INDIVIDUAL) {
|
||||
secStr = `0${secStr}`;
|
||||
}
|
||||
return `${min}:${secStr}`;
|
||||
@ -48,23 +48,15 @@ export class CommonUtil {
|
||||
*/
|
||||
public static getRandomNumber(n: number) {
|
||||
// Generates an array from 0 to n-1.
|
||||
let arr: number[] = Array.from(Array(n), (v, k) => k);
|
||||
let arr: number[] = Array.from(Array(n), (v: number, k: number) => k);
|
||||
// Randomly disrupted.
|
||||
for (let i = 0; i < n; i++) {
|
||||
let j = Math.floor(Math.random() * (arr.length - i) + i);
|
||||
[arr[i], arr[j]] = [arr[j], arr[i]];
|
||||
let tmp = arr[i];
|
||||
arr[i] = arr[j];
|
||||
arr[j] = tmp;
|
||||
}
|
||||
arr.length = n;
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check obj is empty or not.
|
||||
*
|
||||
* @param obj Object.
|
||||
* @returns
|
||||
*/
|
||||
public static isEmpty(obj) {
|
||||
return typeof obj === 'undefined' || obj == null || obj === '';
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2023 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.
|
||||
*/
|
||||
|
||||
export class GlobalContext {
|
||||
private constructor() {
|
||||
}
|
||||
|
||||
private static instance: GlobalContext;
|
||||
private _objects = new Map<string, Object>();
|
||||
|
||||
public static getContext(): GlobalContext {
|
||||
if (!GlobalContext.instance) {
|
||||
GlobalContext.instance = new GlobalContext();
|
||||
}
|
||||
return GlobalContext.instance;
|
||||
}
|
||||
|
||||
getObject(value: string): Object | undefined {
|
||||
return this._objects.get(value);
|
||||
}
|
||||
|
||||
setObject(key: string, objectClass: Object): void {
|
||||
this._objects.set(key, objectClass);
|
||||
}
|
||||
}
|
@ -33,19 +33,19 @@ class Logger {
|
||||
this.domain = domain;
|
||||
}
|
||||
|
||||
debug(...args: any[]): void {
|
||||
debug(...args: string[]): void {
|
||||
hilog.debug(this.domain, this.prefix, this.format, args);
|
||||
}
|
||||
|
||||
info(...args: any[]): void {
|
||||
info(...args: string[]): void {
|
||||
hilog.info(this.domain, this.prefix, this.format, args);
|
||||
}
|
||||
|
||||
warn(...args: any[]): void {
|
||||
warn(...args: string[]): void {
|
||||
hilog.warn(this.domain, this.prefix, this.format, args);
|
||||
}
|
||||
|
||||
error(...args: any[]): void {
|
||||
error(...args: string[]): void {
|
||||
hilog.error(this.domain, this.prefix, this.format, args);
|
||||
}
|
||||
}
|
||||
|
@ -12,9 +12,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import resourceManager from '@ohos.resourceManager';
|
||||
|
||||
import Logger from '../utils/Logger';
|
||||
import { CommonUtil } from './CommonUtil';
|
||||
import { GlobalContext } from './GlobalContext';
|
||||
|
||||
const TAG = '[ResourceManagerUtil]';
|
||||
|
||||
@ -22,7 +23,6 @@ const TAG = '[ResourceManagerUtil]';
|
||||
* Resource management tool class.
|
||||
*/
|
||||
export class ResourceManagerUtil {
|
||||
|
||||
/**
|
||||
* Obtains the description of a media file.
|
||||
*
|
||||
@ -30,12 +30,14 @@ export class ResourceManagerUtil {
|
||||
* @param callback Callback function.
|
||||
*/
|
||||
public static getSrcPath(path: string, callback: Function) {
|
||||
if (CommonUtil.isEmpty(callback)) {
|
||||
if (callback === undefined) {
|
||||
Logger.error(TAG, 'getSrcPath fail,callback is empty.');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
globalThis.resourceManager.getRawFd(path, (error, value) => {
|
||||
let resourceManager = GlobalContext.getContext()
|
||||
.getObject('resourceManager') as resourceManager.ResourceManager;
|
||||
resourceManager.getRawFd(path, (error, value) => {
|
||||
if (error != null) {
|
||||
Logger.error(TAG, `callback getRawFd failed error code: ${error.code}, message: ${error.message}.`);
|
||||
} else {
|
||||
|
@ -14,23 +14,26 @@
|
||||
*/
|
||||
|
||||
import media from '@ohos.multimedia.media';
|
||||
import { MusicItem } from '../common/bean/MusicItem';
|
||||
import { MusicItem } from '../viewmodel/MusicItem';
|
||||
import { PlayMode, PlayerState, StateEvent, CommonConstants } from '../common/constants/CommonConstants';
|
||||
import { BackgroundTaskUtil } from '../common/utils/BackgroundTaskUtil';
|
||||
import { AvSessionUtil } from '../common/utils/AvSessionUtil';
|
||||
import Logger from '../common/utils/Logger';
|
||||
import { CommonUtil } from '../common/utils/CommonUtil';
|
||||
import { GlobalContext } from '../common/utils/GlobalContext';
|
||||
import { PlayBarModel } from '../common/model/PlayBarModel';
|
||||
|
||||
const TAG = '[AudioPlayerController]';
|
||||
|
||||
export class AudioPlayerController {
|
||||
avPlayer: media.AVPlayer;
|
||||
public playBarModel: PlayBarModel;
|
||||
avPlayer?: media.AVPlayer;
|
||||
musicList: Array<MusicItem> = [];
|
||||
currentTimeMs: number = 0; // Current playback position.
|
||||
timeId = CommonConstants.DEFAULT_TIME_ID;
|
||||
avPlayerState = PlayerState.IDLE;
|
||||
|
||||
constructor() {
|
||||
constructor(playBarModel: PlayBarModel) {
|
||||
this.playBarModel = playBarModel;
|
||||
this.initAudioPlayer();
|
||||
}
|
||||
|
||||
@ -43,7 +46,7 @@ export class AudioPlayerController {
|
||||
*/
|
||||
initAudioPlayer() {
|
||||
media.createAVPlayer((error, video) => {
|
||||
if (CommonUtil.isEmpty(video)) {
|
||||
if (video === undefined) {
|
||||
this.avPlayer = video;
|
||||
Logger.error(TAG, `createAVPlayer fail, error: ${error}`);
|
||||
} else {
|
||||
@ -58,13 +61,15 @@ export class AudioPlayerController {
|
||||
*
|
||||
* @param context Context.
|
||||
*/
|
||||
setEventCallBack(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
Logger.info(TAG, 'setEventCallBack fail,context is empty.');
|
||||
setEventCallBack() {
|
||||
if (this.avPlayer === undefined) {
|
||||
return;
|
||||
}
|
||||
// Callback function for state machine changes.
|
||||
this.avPlayer.on('stateChange', async (state) => {
|
||||
if (this.avPlayer === undefined) {
|
||||
return;
|
||||
}
|
||||
switch (state) {
|
||||
case StateEvent.IDLE: // This state machine is triggered after the reset interface is successfully invoked.
|
||||
Logger.info(TAG, 'state idle called');
|
||||
@ -87,12 +92,12 @@ export class AudioPlayerController {
|
||||
if (this.currentTimeMs > 0) {
|
||||
this.avPlayer.seek(this.currentTimeMs);
|
||||
}
|
||||
this.progressChange(context);
|
||||
this.progressChange();
|
||||
break;
|
||||
case StateEvent.COMPLETED:
|
||||
Logger.info(TAG, 'state completed called');
|
||||
BackgroundTaskUtil.stopContinuousTask(getContext(this))
|
||||
this.loopPlay(context);
|
||||
this.loopPlay();
|
||||
break;
|
||||
default:
|
||||
Logger.error('unknown state: ' + state);
|
||||
@ -107,7 +112,7 @@ export class AudioPlayerController {
|
||||
* @param src Resource path.
|
||||
* @param seekTo Playing position.
|
||||
*/
|
||||
async play(src, seekTo) {
|
||||
async play(src: media.AVFileDescriptor, seekTo: number) {
|
||||
Logger.info(TAG, 'audioPlayer play');
|
||||
if (this.timeId === CommonConstants.DEFAULT_TIME_ID) {
|
||||
clearInterval(this.timeId);
|
||||
@ -115,6 +120,9 @@ export class AudioPlayerController {
|
||||
// Enable a long-term task to allow long-term playback in the background.
|
||||
BackgroundTaskUtil.startContinuousTask(getContext(this));
|
||||
this.currentTimeMs = Math.max(0, seekTo);
|
||||
if (this.avPlayer === undefined) {
|
||||
return;
|
||||
}
|
||||
if (this.avPlayerState === PlayerState.INITIALIZED) {
|
||||
await this.avPlayer.reset();
|
||||
Logger.info(TAG, 'play reset success');
|
||||
@ -127,6 +135,9 @@ export class AudioPlayerController {
|
||||
if (this.timeId === CommonConstants.DEFAULT_TIME_ID) {
|
||||
clearInterval(this.timeId);
|
||||
}
|
||||
if (this.avPlayer === undefined) {
|
||||
return;
|
||||
}
|
||||
BackgroundTaskUtil.stopContinuousTask(getContext(this));
|
||||
await this.avPlayer.pause();
|
||||
}
|
||||
@ -142,54 +153,57 @@ export class AudioPlayerController {
|
||||
}
|
||||
}
|
||||
|
||||
progressChange(context) {
|
||||
context.playValue = this.currentTimeMs;
|
||||
context.totalValue = this.avPlayer.duration;
|
||||
progressChange() {
|
||||
this.playBarModel.playValue = this.currentTimeMs;
|
||||
if (this.avPlayer === undefined) {
|
||||
return;
|
||||
}
|
||||
this.playBarModel.totalValue = this.avPlayer.duration;
|
||||
this.timeId = setInterval(() => {
|
||||
context.playValue = this.avPlayer.currentTime;
|
||||
if (this.avPlayer === undefined) {
|
||||
return;
|
||||
}
|
||||
this.playBarModel.playValue = this.avPlayer.currentTime;
|
||||
}, CommonConstants.DELAY_TIME)
|
||||
}
|
||||
|
||||
loopPlay(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
Logger.info(TAG, 'setEventCallBack fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
loopPlay() {
|
||||
this.currentTimeMs = 0;
|
||||
// Play the next song in loop mode.
|
||||
switch (context.playMode) {
|
||||
switch (this.playBarModel.playMode) {
|
||||
case PlayMode.SINGLE_LOOP:
|
||||
this.play(context.musicItem.rawFileDescriptor, 0);
|
||||
this.play(this.playBarModel!.musicItem!.rawFileDescriptor, 0);
|
||||
break;
|
||||
case PlayMode.LIST_LOOP:
|
||||
let nextIndex = this.musicList.length - 1;
|
||||
this.musicList.forEach((item, index) => {
|
||||
if (item.id === context.musicItem.id) {
|
||||
if (item.id === this.playBarModel!.musicItem!.id) {
|
||||
nextIndex = index + 1 > this.musicList.length - 1 ? 0 : index + 1;
|
||||
return;
|
||||
}
|
||||
})
|
||||
context.musicItem = this.musicList[nextIndex];
|
||||
this.play(context.musicItem.rawFileDescriptor, 0);
|
||||
// Sets the current music metadata.
|
||||
AvSessionUtil.setAVMetadata(context);
|
||||
this.playBarModel.musicItem = this.musicList[nextIndex];
|
||||
this.play(this.playBarModel.musicItem.rawFileDescriptor, 0);
|
||||
// Sets the current music metadata.
|
||||
AvSessionUtil.setAVMetadata(this.playBarModel);
|
||||
break;
|
||||
case PlayMode.RANDOM_PLAY:
|
||||
// Obtain the previous song in the random list.
|
||||
let nextIndexRandom = globalThis.randomList.length - 1;
|
||||
globalThis.randomList.forEach((item, index) => {
|
||||
if (item === context.musicItem.id) {
|
||||
nextIndexRandom = index + 1 > globalThis.randomList.length - 1 ? 0 : index + 1;
|
||||
// Obtain the previous song in the random list.
|
||||
let randomList = GlobalContext.getContext().getObject('randomList') as number[];
|
||||
let nextIndexRandom = randomList.length - 1;
|
||||
randomList.forEach((item, index) => {
|
||||
if (item === this.playBarModel!.musicItem!.id) {
|
||||
nextIndexRandom = index + 1 > randomList.length - 1 ? 0 : index + 1;
|
||||
return;
|
||||
}
|
||||
})
|
||||
context.musicItem = this.musicList[globalThis.randomList[nextIndexRandom]];
|
||||
this.play(context.musicItem.rawFileDescriptor, 0);
|
||||
// Sets the current music metadata.
|
||||
AvSessionUtil.setAVMetadata(context);
|
||||
this.playBarModel.musicItem = this.musicList[randomList[nextIndexRandom]];
|
||||
this.play(this.playBarModel.musicItem.rawFileDescriptor, 0);
|
||||
// Sets the current music metadata.
|
||||
AvSessionUtil.setAVMetadata(this.playBarModel);
|
||||
break;
|
||||
default:
|
||||
Logger.error('unknown mode: ' + context.playMode);
|
||||
Logger.error('unknown mode: ' + this.playBarModel.playMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -18,53 +18,55 @@ import { CommonUtil } from '../common/utils/CommonUtil';
|
||||
import { AvSessionUtil } from '../common/utils/AvSessionUtil';
|
||||
import { PlayState, PlayMode, CommonConstants } from '../common/constants/CommonConstants';
|
||||
import Logger from '../common/utils/Logger';
|
||||
import { GlobalContext } from '../common/utils/GlobalContext';
|
||||
import { AudioPlayerController } from './AudioPlayerControllerl';
|
||||
import { MusicItem } from '../viewmodel/MusicItem';
|
||||
import { PlayBarModel } from '../common/model/PlayBarModel';
|
||||
|
||||
const TAG = '[PlayBarController]';
|
||||
|
||||
export class PlayBarController {
|
||||
public playBarModel: PlayBarModel;
|
||||
|
||||
constructor(playBarModel: PlayBarModel) {
|
||||
this.playBarModel = playBarModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle playback mode.
|
||||
*
|
||||
* @param context Context.
|
||||
*/
|
||||
switchPlayMode(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
Logger.info(TAG, 'switchPlayMode fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
context.playMode = (context.playMode + 1) % CommonConstants.MODE_QUANTITY;
|
||||
if (context.playMode === PlayMode.LIST_LOOP) {
|
||||
context.playModeIcon = $r('app.media.ic_list_mode');
|
||||
} else if (context.playMode === PlayMode.SINGLE_LOOP) {
|
||||
context.playModeIcon = $r('app.media.ic_single_mode');
|
||||
switchPlayMode() {
|
||||
this.playBarModel.playMode = (this.playBarModel.playMode + 1) % CommonConstants.MODE_QUANTITY;
|
||||
if (this.playBarModel.playMode === PlayMode.LIST_LOOP) {
|
||||
this.playBarModel.playModeIcon = $r('app.media.ic_list_mode');
|
||||
} else if (this.playBarModel.playMode === PlayMode.SINGLE_LOOP) {
|
||||
this.playBarModel.playModeIcon = $r('app.media.ic_single_mode');
|
||||
} else {
|
||||
context.playModeIcon = $r('app.media.ic_random_mode');
|
||||
this.playBarModel.playModeIcon = $r('app.media.ic_random_mode');
|
||||
// Random mode, generating random play list.
|
||||
globalThis.randomMusicList = [];
|
||||
globalThis.randomList = CommonUtil.getRandomNumber(CommonConstants.MUSICS_QUANTITY);
|
||||
let randomList = CommonUtil.getRandomNumber(CommonConstants.MUSICS_QUANTITY);
|
||||
GlobalContext.getContext().setObject('randomList', randomList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switching the Playback Status.
|
||||
*
|
||||
* @param context Context.
|
||||
* @param playState
|
||||
*/
|
||||
switchPlayState(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
Logger.info(TAG, 'switchPlayState fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
if (context.playState === PlayState.PLAY) {
|
||||
context.playState = PlayState.PAUSE;
|
||||
context.playStateIcon = $r('app.media.ic_pause');
|
||||
globalThis.AudioPlayerController.pause();
|
||||
switchPlayState(playState: number) {
|
||||
let playController = GlobalContext.getContext().getObject('audioPlayerController') as AudioPlayerController;
|
||||
if (playState === PlayState.PLAY) {
|
||||
this.playBarModel.playState = PlayState.PAUSE;
|
||||
this.playBarModel.playStateIcon = $r('app.media.ic_pause');
|
||||
playController.pause();
|
||||
AvSessionUtil.setAVPlayState(avSession.PlaybackState.PLAYBACK_STATE_PAUSE);
|
||||
} else {
|
||||
context.playState = PlayState.PLAY;
|
||||
context.playStateIcon = $r('app.media.ic_play');
|
||||
Logger.info(TAG, `rawFileDescriptor: ${context.musicItem.rawFileDescriptor} playValue ${context.playValue}`);
|
||||
globalThis.AudioPlayerController.play(context.musicItem.rawFileDescriptor, context.playValue);
|
||||
this.playBarModel.playState = PlayState.PLAY;
|
||||
this.playBarModel.playStateIcon = $r('app.media.ic_play');
|
||||
Logger.info(TAG, `rawFileDescriptor: ${this.playBarModel!.musicItem!.rawFileDescriptor},
|
||||
playValue ${this.playBarModel!.playValue}`);
|
||||
playController.play(this.playBarModel.musicItem!.rawFileDescriptor, this.playBarModel.playValue);
|
||||
AvSessionUtil.setAVPlayState(avSession.PlaybackState.PLAYBACK_STATE_PLAY);
|
||||
}
|
||||
}
|
||||
@ -72,78 +74,76 @@ export class PlayBarController {
|
||||
/**
|
||||
* Previous song.
|
||||
*
|
||||
* @param context Context.
|
||||
* @param musicList
|
||||
* @param playState
|
||||
*/
|
||||
getPreviousMusic(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
Logger.info(TAG, 'getPreviousMusic fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
if (context.playMode === PlayMode.RANDOM_PLAY) {
|
||||
getPreviousMusic(musicList: Array<MusicItem>, playState: number) {
|
||||
if (this.playBarModel.playMode === PlayMode.RANDOM_PLAY) {
|
||||
// Obtain the previous song in the random list.
|
||||
let preIndex = 0;
|
||||
globalThis.randomList.forEach((item, index) => {
|
||||
if (item === context.musicItem.id) {
|
||||
preIndex = index - 1 < 0 ? globalThis.randomList.length - 1 : index - 1;
|
||||
let randomList = GlobalContext.getContext().getObject('randomList') as number[];
|
||||
randomList.forEach((item: number, index: number) => {
|
||||
if (item === this.playBarModel!.musicItem!.id) {
|
||||
preIndex = index - 1 < 0 ? randomList.length - 1 : index - 1;
|
||||
return;
|
||||
}
|
||||
})
|
||||
context.musicItem = context.musicList[globalThis.randomList[preIndex]];
|
||||
this.playBarModel.musicItem = musicList[randomList[preIndex]];
|
||||
} else {
|
||||
let preIndex = 0;
|
||||
context.musicList.forEach((item, index) => {
|
||||
if (item.id === context.musicItem.id) {
|
||||
preIndex = index - 1 < 0 ? context.musicList.length - 1 : index - 1;
|
||||
musicList.forEach((item: MusicItem, index: number) => {
|
||||
if (item.id === this.playBarModel.musicItem!.id) {
|
||||
preIndex = index - 1 < 0 ? musicList.length - 1 : index - 1;
|
||||
return;
|
||||
}
|
||||
})
|
||||
context.musicItem = context.musicList[preIndex];
|
||||
this.playBarModel.musicItem = musicList[preIndex];
|
||||
}
|
||||
Logger.info(TAG, 'state pre called' + context.playValue);
|
||||
globalThis.AudioPlayerController.play(context.musicItem.rawFileDescriptor, 0);
|
||||
context.playState = PlayState.PLAY;
|
||||
context.playStateIcon = $r('app.media.ic_play');
|
||||
Logger.info(TAG, 'state pre called' + this.playBarModel.playValue);
|
||||
let playController = GlobalContext.getContext().getObject('audioPlayerController') as AudioPlayerController;
|
||||
playController.play(this.playBarModel.musicItem.rawFileDescriptor, 0);
|
||||
this.playBarModel.playState = PlayState.PLAY;
|
||||
this.playBarModel.playStateIcon = $r('app.media.ic_play');
|
||||
// Sets the current music metadata.
|
||||
AvSessionUtil.setAVMetadata(context);
|
||||
AvSessionUtil.setAVMetadata(this.playBarModel);
|
||||
AvSessionUtil.setAVPlayState(avSession.PlaybackState.PLAYBACK_STATE_PLAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next song.
|
||||
*
|
||||
* @param context Context.
|
||||
* @param musicList
|
||||
* @param playState
|
||||
*/
|
||||
getNextMusic(context) {
|
||||
if (CommonUtil.isEmpty(context)) {
|
||||
Logger.info(TAG, 'getNextMusic fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
getNextMusic(musicList: Array<MusicItem>) {
|
||||
// Random mode, which is used to obtain the next song randomly.
|
||||
if (context.playMode === PlayMode.RANDOM_PLAY) {
|
||||
if (this.playBarModel.playMode === PlayMode.RANDOM_PLAY) {
|
||||
// Obtain the previous song in the random list.
|
||||
let nextIndex = globalThis.randomList.length - 1;
|
||||
globalThis.randomList.forEach((item, index) => {
|
||||
if (item === context.musicItem.id) {
|
||||
nextIndex = index + 1 > globalThis.randomList.length - 1 ? 0 : index + 1;
|
||||
let randomList = GlobalContext.getContext().getObject('randomList') as number[];
|
||||
let nextIndex = randomList.length - 1;
|
||||
randomList.forEach((item: number, index: number) => {
|
||||
if (item === this.playBarModel!.musicItem!.id) {
|
||||
nextIndex = index + 1 > randomList.length - 1 ? 0 : index + 1;
|
||||
return;
|
||||
}
|
||||
})
|
||||
context.musicItem = context.musicList[globalThis.randomList[nextIndex]]
|
||||
this.playBarModel.musicItem = musicList[randomList[nextIndex]]
|
||||
} else {
|
||||
let nextIndex = context.musicList.length - 1;
|
||||
context.musicList.forEach((item, index) => {
|
||||
if (item.id === context.musicItem.id) {
|
||||
nextIndex = index + 1 > context.musicList.length - 1 ? 0 : index + 1;
|
||||
let nextIndex = musicList.length - 1;
|
||||
musicList.forEach((item: MusicItem, index: number) => {
|
||||
if (item.id === this.playBarModel!.musicItem!.id) {
|
||||
nextIndex = index + 1 > musicList.length - 1 ? 0 : index + 1;
|
||||
return;
|
||||
}
|
||||
})
|
||||
context.musicItem = context.musicList[nextIndex];
|
||||
this.playBarModel.musicItem = musicList[nextIndex];
|
||||
}
|
||||
globalThis.AudioPlayerController.play(context.musicItem.rawFileDescriptor, 0);
|
||||
context.playState = PlayState.PLAY;
|
||||
context.playStateIcon = $r('app.media.ic_play');
|
||||
let playController = GlobalContext.getContext().getObject('audioPlayerController') as AudioPlayerController;
|
||||
playController.play(this.playBarModel.musicItem.rawFileDescriptor, 0);
|
||||
this.playBarModel.playState = PlayState.PLAY;
|
||||
this.playBarModel.playStateIcon = $r('app.media.ic_play');
|
||||
// Sets the current music metadata.
|
||||
AvSessionUtil.setAVMetadata(context);
|
||||
AvSessionUtil.setAVMetadata(this.playBarModel);
|
||||
AvSessionUtil.setAVPlayState(avSession.PlaybackState.PLAYBACK_STATE_PLAY);
|
||||
}
|
||||
}
|
@ -18,41 +18,48 @@ import Window from '@ohos.window';
|
||||
import avSession from '@ohos.multimedia.avsession';
|
||||
import { AudioPlayerController } from '../controller/AudioPlayerControllerl';
|
||||
import Logger from '../common/utils/Logger';
|
||||
import { GlobalContext } from '../common/utils/GlobalContext';
|
||||
import { PlayBarModel } from '../common/model/PlayBarModel';
|
||||
|
||||
export default class EntryAbility extends UIAbility {
|
||||
onDestroy() {
|
||||
Logger.info('Ability onDestroy');
|
||||
// Release resources.
|
||||
globalThis.AudioPlayerController.release();
|
||||
globalThis.currentSession.off('play');
|
||||
globalThis.currentSession.off('pause');
|
||||
globalThis.currentSession.deactivate().then(() => {
|
||||
globalThis.currentSession.destroy();
|
||||
let audioPlayerController = GlobalContext.getContext().getObject('audioPlayerController') as AudioPlayerController;
|
||||
audioPlayerController.release();
|
||||
|
||||
let currentSession = GlobalContext.getContext().getObject('currentSession') as avSession.AVSession;
|
||||
currentSession.off('play');
|
||||
currentSession.off('pause');
|
||||
currentSession.deactivate().then(() => {
|
||||
currentSession.destroy();
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: Window.WindowStage) {
|
||||
// Main window is created, set main page for this ability.
|
||||
let context = this.context;
|
||||
globalThis.resourceManager = context.resourceManager;
|
||||
let resourceManager = context.resourceManager;
|
||||
GlobalContext.getContext().setObject('resourceManager', resourceManager);
|
||||
|
||||
// Create an audioPlayer instance.
|
||||
globalThis.AudioPlayerController = new AudioPlayerController();
|
||||
let audioPlayerController = new AudioPlayerController(new PlayBarModel());
|
||||
GlobalContext.getContext().setObject('audioPlayerController', audioPlayerController);
|
||||
|
||||
// Creating an Audio Session.
|
||||
avSession.createAVSession(context, 'AudioAppSample', 'audio').then((session) => {
|
||||
globalThis.currentSession = session;
|
||||
globalThis.currentSession.activate(); // Activating a Session.
|
||||
}).catch((err) => {
|
||||
Logger.error(`createAVSession : ERROR : ${err.message}`);
|
||||
session.activate();
|
||||
GlobalContext.getContext().setObject('currentSession', session);
|
||||
}).catch((err: Error) => {
|
||||
Logger.error(`createAVSession fail, Cause: ${err}`);
|
||||
});
|
||||
|
||||
windowStage.loadContent('pages/AudioStartUp', (err, data) => {
|
||||
if (err.code) {
|
||||
Logger.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||
Logger.error('testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||
return;
|
||||
}
|
||||
Logger.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
|
||||
Logger.info('testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
|
||||
});
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ import { CommonConstants } from '../common/constants/CommonConstants';
|
||||
@Entry
|
||||
@Component
|
||||
struct AudioStartUp {
|
||||
private timeId: number;
|
||||
private timeId: number = -1;
|
||||
|
||||
aboutToAppear() {
|
||||
// The play list page is automatically displayed 1s later.
|
||||
@ -28,7 +28,7 @@ struct AudioStartUp {
|
||||
router.pushUrl({
|
||||
url: CommonConstants.PAGE_MUSIC_LIST,
|
||||
params: {}
|
||||
}).catch(err => {
|
||||
}).catch((err: Error) => {
|
||||
Logger.error('push url fail: ' + err);
|
||||
})
|
||||
}, CommonConstants.DELAY_TIME)
|
||||
@ -43,14 +43,15 @@ struct AudioStartUp {
|
||||
Column() {
|
||||
Column() {
|
||||
Image($r('app.media.icon'))
|
||||
.width(CommonConstants.START_UP_PAGE.IMAGE_WIDTH)
|
||||
.height(CommonConstants.START_UP_PAGE.IMAGE_HEIGHT)
|
||||
.width(CommonConstants.START_IMAGE_WIDTH)
|
||||
.height(CommonConstants.START_IMAGE_HEIGHT)
|
||||
.objectFit(ImageFit.Contain)
|
||||
}
|
||||
.height(CommonConstants.START_UP_PAGE.IMAGE_CONTAINER)
|
||||
.height(CommonConstants.START_IMAGE_CONTAINER)
|
||||
.width(CommonConstants.FULL_WIDTH)
|
||||
.alignItems(HorizontalAlign.Center)
|
||||
.justifyContent(FlexAlign.Center)
|
||||
|
||||
Text($r('app.string.app_name'))
|
||||
.fontSize($r("app.float.start_title"))
|
||||
.textAlign(TextAlign.Center)
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
import router from '@ohos.router';
|
||||
import Logger from '../common/utils/Logger';
|
||||
import { MusicItem } from '../common/bean/MusicItem';
|
||||
import { MusicItem } from '../viewmodel/MusicItem';
|
||||
import { MusicView } from '../view/MusicView';
|
||||
import { CommonConstants } from '../common/constants/CommonConstants';
|
||||
import { initializeMusic } from '../viewmodel/MusicViewModel';
|
||||
@ -34,13 +34,13 @@ struct MusicList {
|
||||
Column() {
|
||||
Text($r('app.string.hot_music'))
|
||||
.fontSize($r('app.float.musicList_title'))
|
||||
.width(CommonConstants.MUSIC_LIST_PAGE.TEXT_WIDTH)
|
||||
.height(CommonConstants.MUSIC_LIST_PAGE.TEXT_HEIGHT)
|
||||
.width(CommonConstants.TEXT_WIDTH)
|
||||
.height(CommonConstants.TEXT_HEIGHT)
|
||||
.margin({
|
||||
left: CommonConstants.MUSIC_LIST_PAGE.TEXT_MARGIN_LEFT,
|
||||
top: CommonConstants.MUSIC_LIST_PAGE.TEXT_MARGIN_TOP,
|
||||
right: CommonConstants.MUSIC_LIST_PAGE.TEXT_MARGIN_RIGHT,
|
||||
bottom: CommonConstants.MUSIC_LIST_PAGE.TEXT_MARGIN_BOTTOM
|
||||
left: CommonConstants.TEXT_MARGIN_LEFT,
|
||||
top: CommonConstants.TEXT_MARGIN_TOP,
|
||||
right: CommonConstants.TEXT_MARGIN_RIGHT,
|
||||
bottom: CommonConstants.TEXT_MARGIN_BOTTOM
|
||||
})
|
||||
ForEach(this.musicData, (item: MusicItem) => {
|
||||
MusicView({ item: item })
|
||||
@ -48,11 +48,11 @@ struct MusicList {
|
||||
router.pushUrl({
|
||||
url: CommonConstants.PAGE_PLAY,
|
||||
params: { 'item': item }
|
||||
}).catch((error) => {
|
||||
}).catch((error: Error) => {
|
||||
Logger.error(`go to play list fail,error: ${error}`);
|
||||
})
|
||||
})
|
||||
}, item => JSON.stringify(item))
|
||||
}, (item: MusicItem) => JSON.stringify(item))
|
||||
}
|
||||
}
|
||||
}
|
@ -14,40 +14,43 @@
|
||||
*/
|
||||
|
||||
import router from '@ohos.router';
|
||||
import { MusicItem } from '../common/bean/MusicItem';
|
||||
import { MusicItem } from '../viewmodel/MusicItem';
|
||||
import { AvSessionUtil } from '../common/utils/AvSessionUtil';
|
||||
import { PlayBarView } from '../view/PlayBarView';
|
||||
import { ProgressView } from '../view/ProgressView';
|
||||
import { MusicCardView } from '../view/MusicCardView';
|
||||
import { CommonConstants, PlayMode } from '../common/constants/CommonConstants';
|
||||
import { CommonUtil } from '../common/utils/CommonUtil';
|
||||
import Logger from '../common/utils/Logger';
|
||||
import { GlobalContext } from '../common/utils/GlobalContext';
|
||||
import { AudioPlayerController } from '../controller/AudioPlayerControllerl';
|
||||
import { PlayBarModel } from '../common/model/PlayBarModel';
|
||||
import { PlayBarController } from '../controller/PlayBarController';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Play {
|
||||
@StorageLink('musicList') musicList: Array<MusicItem> = [];
|
||||
@State musicItem: MusicItem = this.musicList[0];
|
||||
@State playValue: number = CommonConstants.START_POSITION; // Progress bar position.
|
||||
@State totalValue: number = CommonConstants.TOTAL_VALUE; // Total length of the progress bar.
|
||||
@State playMode: number = PlayMode.LIST_LOOP; // Playback mode.
|
||||
@State playStateIcon: Resource = $r('app.media.ic_play') // Playback status icon.
|
||||
@Provide playBarModel: PlayBarModel = new PlayBarModel();
|
||||
playBarController: PlayBarController = new PlayBarController(this.playBarModel);
|
||||
|
||||
aboutToAppear() {
|
||||
globalThis.AudioPlayerController.setMusicList(this.musicList);
|
||||
let playController = GlobalContext.getContext().getObject('audioPlayerController') as AudioPlayerController;
|
||||
playController.setMusicList(this.musicList);
|
||||
// Obtain the music file to be played.
|
||||
this.musicItem = router.getParams()['item'];
|
||||
if (CommonUtil.isEmpty(this.musicItem)) {
|
||||
let params = router.getParams() as Record<string, Object>;
|
||||
this.playBarModel.musicItem = params.item as MusicItem;
|
||||
if (this.playBarModel.musicItem === undefined) {
|
||||
Logger.error('play fail,musicItem is empty.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Access the playback control center.
|
||||
AvSessionUtil.initAvSession(this);
|
||||
AvSessionUtil.initAvSession(this.playBarModel);
|
||||
|
||||
// Setting the media source triggers the dataLoad callback.
|
||||
globalThis.AudioPlayerController.setEventCallBack(this);
|
||||
globalThis.AudioPlayerController.play(this.musicItem.rawFileDescriptor, CommonConstants.START_POSITION);
|
||||
playController.playBarModel = this.playBarModel;
|
||||
playController.setEventCallBack();
|
||||
playController.play(this.playBarModel.musicItem.rawFileDescriptor, CommonConstants.START_POSITION);
|
||||
}
|
||||
|
||||
build() {
|
||||
@ -56,37 +59,34 @@ struct Play {
|
||||
Navigator({ target: CommonConstants.PAGE_MUSIC_LIST, type: NavigationType.Back }) {
|
||||
Image($r('app.media.ic_back'))
|
||||
.objectFit(ImageFit.Contain)
|
||||
.width(CommonConstants.PLAY_PAGE.NAVIGATOR_WIDTH)
|
||||
.height(CommonConstants.PLAY_PAGE.NAVIGATOR_HEIGHT)
|
||||
.width(CommonConstants.NAVIGATOR_WIDTH)
|
||||
.height(CommonConstants.NAVIGATOR_HEIGHT)
|
||||
}
|
||||
|
||||
Text($r('app.string.play_title'))
|
||||
.fontSize($r('app.float.play_text'))
|
||||
.fontWeight(CommonConstants.FONT_WEIGHT_BOLDER)
|
||||
.fontColor($r("app.color.font_color_black"))
|
||||
.layoutWeight(CommonConstants.PLAY_PAGE.LAYOUT_WEIGHT)
|
||||
.layoutWeight(CommonConstants.LAYOUT_WEIGHT)
|
||||
.textAlign(TextAlign.Center)
|
||||
.width(CommonConstants.FULL_WIDTH)
|
||||
}
|
||||
.width(CommonConstants.FULL_WIDTH)
|
||||
.padding({
|
||||
left: CommonConstants.PLAY_PAGE.NAVIGATOR_PADDING_LEFT,
|
||||
right: CommonConstants.PLAY_PAGE.NAVIGATOR_PADDING_RIGHT
|
||||
left: CommonConstants.NAVIGATOR_PADDING_LEFT,
|
||||
right: CommonConstants.NAVIGATOR_PADDING_RIGHT
|
||||
})
|
||||
.margin({
|
||||
top: CommonConstants.PLAY_PAGE.NAVIGATOR_PADDING_TOP,
|
||||
bottom: CommonConstants.PLAY_PAGE.NAVIGATOR_PADDING_BOTTOM
|
||||
top: CommonConstants.NAVIGATOR_PADDING_TOP,
|
||||
bottom: CommonConstants.NAVIGATOR_PADDING_BOTTOM
|
||||
})
|
||||
|
||||
Column() {
|
||||
MusicCardView({ musicItem: $musicItem })
|
||||
ProgressView({ playValue: $playValue, totalValue: $totalValue })
|
||||
PlayBarView({
|
||||
musicItem: $musicItem,
|
||||
playMode: $playMode,
|
||||
playValue: $playValue,
|
||||
playStateIcon: $playStateIcon
|
||||
})
|
||||
MusicCardView()
|
||||
ProgressView()
|
||||
PlayBarView({ playBarController: this.playBarController })
|
||||
}
|
||||
.width(CommonConstants.PLAY_PAGE.CONTROL_WIDTH)
|
||||
.width(CommonConstants.CONTROL_WIDTH)
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
}
|
||||
.height(CommonConstants.FULL_HEIGHT)
|
||||
|
@ -13,34 +13,34 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { MusicItem } from '../common/bean/MusicItem';
|
||||
import { CommonConstants } from '../common/constants/CommonConstants';
|
||||
import { PlayBarModel } from '../common/model/PlayBarModel';
|
||||
|
||||
@Component
|
||||
export struct MusicCardView {
|
||||
@Link musicItem: MusicItem;
|
||||
@Consume playBarModel: PlayBarModel;
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Image($r('app.media.ic_play_icon'))
|
||||
.width(CommonConstants.FULL_WIDTH)
|
||||
.height(CommonConstants.MUSIC_CARD_VIEW.IMAGE_HEIGHT)
|
||||
Text(this.musicItem.name)
|
||||
.height(CommonConstants.IMAGE_HEIGHT)
|
||||
Text(this.playBarModel.musicItem!.name)
|
||||
.fontSize($r('app.float.music_name'))
|
||||
.fontColor($r("app.color.music_card_color"))
|
||||
.fontWeight(CommonConstants.FONT_WEIGHT_BOLDER)
|
||||
.margin({ top: CommonConstants.MUSIC_CARD_VIEW.NAME_MARGIN_TOP })
|
||||
Text(this.musicItem.singer)
|
||||
.margin({ top: CommonConstants.NAME_MARGIN_TOP })
|
||||
Text(this.playBarModel.musicItem!.singer)
|
||||
.fontSize($r('app.float.music_singer'))
|
||||
.fontColor($r("app.color.music_card_color"))
|
||||
.fontWeight(FontWeight.Normal)
|
||||
.margin({ top: CommonConstants.MUSIC_CARD_VIEW.SINGER_MARGIN_TOP })
|
||||
Text($r('app.string.lyrics', this.musicItem.lyrics))
|
||||
.margin({ top: CommonConstants.SINGER_MARGIN_TOP })
|
||||
Text($r('app.string.lyrics', this.playBarModel.musicItem!.lyrics))
|
||||
.fontSize($r('app.float.music_lyrics'))
|
||||
.fontColor($r("app.color.music_card_color"))
|
||||
.fontWeight(FontWeight.Normal)
|
||||
.opacity($r('app.float.lyrics_opacity'))
|
||||
.margin({ top: CommonConstants.MUSIC_CARD_VIEW.LYRICS_MARGIN_TOP })
|
||||
.margin({ top: CommonConstants.LYRICS_MARGIN_TOP })
|
||||
}
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
}
|
||||
|
@ -13,19 +13,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { MusicItem } from '../common/bean/MusicItem';
|
||||
import { MusicItem } from '../viewmodel/MusicItem';
|
||||
import { CommonConstants } from '../common/constants/CommonConstants';
|
||||
|
||||
@Component
|
||||
export struct MusicView {
|
||||
private item: MusicItem;
|
||||
private item: MusicItem = new MusicItem();
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Row() {
|
||||
Image(this.item.image)
|
||||
.height(CommonConstants.MUSIC_VIEW.IMAGE_HEIGHT)
|
||||
.width(CommonConstants.MUSIC_VIEW.IMAGE_WIDTH)
|
||||
.height(CommonConstants.MUSIC_IMAGE_HEIGHT)
|
||||
.width(CommonConstants.IMAGE_WIDTH)
|
||||
Column() {
|
||||
Text(this.item.name)
|
||||
.fontSize($r('app.float.musicView_name'))
|
||||
@ -37,17 +37,17 @@ export struct MusicView {
|
||||
.fontWeight(CommonConstants.FONT_WEIGHT_BOLDER)
|
||||
.opacity($r('app.float.singer_opacity'))
|
||||
}
|
||||
.margin({ left: CommonConstants.MUSIC_VIEW.ROW_MARGIN_LEFT })
|
||||
.margin({ left: CommonConstants.ROW_MARGIN_LEFT })
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
}
|
||||
.width(CommonConstants.FULL_WIDTH)
|
||||
.alignSelf(ItemAlign.Start)
|
||||
}
|
||||
.margin({
|
||||
left: CommonConstants.MUSIC_VIEW.PAGE_MARGIN_LEFT,
|
||||
top: CommonConstants.MUSIC_VIEW.PAGE_MARGIN_TOP,
|
||||
right: CommonConstants.MUSIC_VIEW.PAGE_MARGIN_RIGHT,
|
||||
bottom: CommonConstants.MUSIC_VIEW.PAGE_MARGIN_BUTTON
|
||||
left: CommonConstants.PAGE_MARGIN_LEFT,
|
||||
top: CommonConstants.MUSIC_MARGIN_TOP,
|
||||
right: CommonConstants.PAGE_MARGIN_RIGHT,
|
||||
bottom: CommonConstants.PAGE_MARGIN_BUTTON
|
||||
})
|
||||
}
|
||||
}
|
@ -14,72 +14,65 @@
|
||||
*/
|
||||
|
||||
import { PlayListDialogView } from '../view/PlayListDialogView';
|
||||
import { MusicItem } from '../common/bean/MusicItem';
|
||||
import { MusicItem } from '../viewmodel/MusicItem';
|
||||
import { PlayBarController } from '../controller/PlayBarController';
|
||||
import { CommonConstants, PlayState } from '../common/constants/CommonConstants';
|
||||
import { CommonConstants } from '../common/constants/CommonConstants';
|
||||
import { PlayBarModel } from '../common/model/PlayBarModel';
|
||||
|
||||
@Component
|
||||
export struct PlayBarView {
|
||||
@StorageLink('musicList') musicList: Array<MusicItem> = [];
|
||||
@Link musicItem: MusicItem;
|
||||
@State playModeIcon: Resource = $r('app.media.ic_list_mode'); // Playback mode icon.
|
||||
@Link playStateIcon: Resource;
|
||||
@Link playMode: number; // Playback mode.
|
||||
@Link playValue: number; // Playback duration position.
|
||||
playState: number = PlayState.PLAY; // Playback status.
|
||||
PlayBarController: PlayBarController = new PlayBarController();
|
||||
private playBarController?: PlayBarController;
|
||||
@Consume playBarModel: PlayBarModel;
|
||||
dialogController: CustomDialogController = new CustomDialogController({
|
||||
builder: PlayListDialogView({
|
||||
musicList: $musicList,
|
||||
musicItem: $musicItem,
|
||||
playModeIcon: $playModeIcon,
|
||||
playMode: $playMode
|
||||
musicList: $musicList
|
||||
}),
|
||||
alignment: DialogAlignment.Bottom
|
||||
})
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Image(this.playModeIcon)
|
||||
.width(CommonConstants.CONTROL_VIEW.MODE_ICON_WIDTH)
|
||||
.height(CommonConstants.CONTROL_VIEW.MODE_ICON_HEIGHT)
|
||||
Image(this.playBarModel.playModeIcon)
|
||||
.width(CommonConstants.MODE_ICON_WIDTH)
|
||||
.height(CommonConstants.MODE_ICON_HEIGHT)
|
||||
.onClick(() => {
|
||||
this.PlayBarController.switchPlayMode(this);
|
||||
this.playBarController!.switchPlayMode();
|
||||
})
|
||||
Blank()
|
||||
.layoutWeight(1)
|
||||
Image($r('app.media.ic_previous'))
|
||||
.width(CommonConstants.CONTROL_VIEW.PREVIOUS_WIDTH)
|
||||
.height(CommonConstants.CONTROL_VIEW.PREVIOUS_HEIGHT)
|
||||
.width(CommonConstants.PREVIOUS_WIDTH)
|
||||
.height(CommonConstants.PREVIOUS_HEIGHT)
|
||||
.onClick(() => {
|
||||
this.PlayBarController.getPreviousMusic(this);
|
||||
this.playBarController!.getPreviousMusic(this.musicList, this.playBarModel.playState);
|
||||
})
|
||||
Blank()
|
||||
.layoutWeight(1)
|
||||
Image(this.playStateIcon)
|
||||
.width(CommonConstants.CONTROL_VIEW.STATE_ICON_WIDTH)
|
||||
.height(CommonConstants.CONTROL_VIEW.STATE_ICON_HEIGHT)
|
||||
Image(this.playBarModel.playStateIcon)
|
||||
.width(CommonConstants.STATE_ICON_WIDTH)
|
||||
.height(CommonConstants.STATE_ICON_HEIGHT)
|
||||
.objectFit(ImageFit.Contain)
|
||||
.onClick(() => {
|
||||
this.PlayBarController.switchPlayState(this);
|
||||
this.playBarController!.switchPlayState(this.playBarModel.playState);
|
||||
})
|
||||
Blank()
|
||||
.layoutWeight(1)
|
||||
Image($r('app.media.ic_next'))
|
||||
.width(CommonConstants.CONTROL_VIEW.NEXT_WIDTH)
|
||||
.height(CommonConstants.CONTROL_VIEW.NEXT_HEIGHT)
|
||||
.width(CommonConstants.NEXT_WIDTH)
|
||||
.height(CommonConstants.NEXT_HEIGHT)
|
||||
.onClick(() => {
|
||||
this.PlayBarController.getNextMusic(this);
|
||||
this.playBarController!.getNextMusic(this.musicList);
|
||||
})
|
||||
Blank()
|
||||
.layoutWeight(1)
|
||||
Image($r('app.media.ic_play_list'))
|
||||
.width(CommonConstants.CONTROL_VIEW.PLAY_LIST_WIDTH)
|
||||
.height(CommonConstants.CONTROL_VIEW.PLAY_LIST_HEIGHT)
|
||||
.width(CommonConstants.PLAY_LIST_WIDTH)
|
||||
.height(CommonConstants.PLAY_LIST_HEIGHT)
|
||||
.onClick(() => {
|
||||
this.dialogController.open();
|
||||
})
|
||||
}
|
||||
.margin({ top: CommonConstants.CONTROL_VIEW.PAGE_MARGIN_TOP })
|
||||
.margin({ top: CommonConstants.PAGE_MARGIN_TOP })
|
||||
}
|
||||
}
|
@ -14,22 +14,21 @@
|
||||
*/
|
||||
|
||||
import { PlayListMusicView } from './PlayListMusicView';
|
||||
import { MusicItem } from '../common/bean/MusicItem';
|
||||
import { MusicItem } from '../viewmodel/MusicItem';
|
||||
import { CommonConstants, PlayMode } from '../common/constants/CommonConstants';
|
||||
import { PlayBarModel } from '../common/model/PlayBarModel';
|
||||
|
||||
@CustomDialog
|
||||
export struct PlayListDialogView {
|
||||
@Link musicList: Array<MusicItem>;
|
||||
@Link musicItem: MusicItem;
|
||||
@Link playModeIcon: Resource;
|
||||
@Link playMode: number;
|
||||
@Consume playBarModel: PlayBarModel;
|
||||
@State playModeDesc: Resource = $r('app.string.sequence');
|
||||
controller: CustomDialogController;
|
||||
controller: CustomDialogController = new CustomDialogController({ builder: {} });
|
||||
|
||||
switchPlayModeDesc() {
|
||||
if (this.playMode === PlayMode.RANDOM_PLAY) {
|
||||
if (this.playBarModel.playMode === PlayMode.RANDOM_PLAY) {
|
||||
this.playModeDesc = $r('app.string.random');
|
||||
} else if (this.playMode === PlayMode.SINGLE_LOOP) {
|
||||
} else if (this.playBarModel.playMode === PlayMode.SINGLE_LOOP) {
|
||||
this.playModeDesc = $r('app.string.single');
|
||||
} else {
|
||||
this.playModeDesc = $r('app.string.sequence');
|
||||
@ -43,10 +42,10 @@ export struct PlayListDialogView {
|
||||
build() {
|
||||
Column() {
|
||||
Row() {
|
||||
Image(this.playModeIcon)
|
||||
.width(CommonConstants.LIST_DIALOG.IMAGE_WIDTH)
|
||||
.height(CommonConstants.LIST_DIALOG.IMAGE_HEIGHT)
|
||||
.margin({ right: CommonConstants.LIST_DIALOG.IMAGE_MARGIN_RIGHT })
|
||||
Image(this.playBarModel.playModeIcon)
|
||||
.width(CommonConstants.DIALOG_IMAGE_WIDTH)
|
||||
.height(CommonConstants.DIALOG_IMAGE_HEIGHT)
|
||||
.margin({ right: CommonConstants.IMAGE_MARGIN_RIGHT })
|
||||
Text(this.playModeDesc)
|
||||
.fontSize($r("app.float.play_mode_description"))
|
||||
.fontWeight(CommonConstants.FONT_WEIGHT_BOLDER)
|
||||
@ -54,32 +53,33 @@ export struct PlayListDialogView {
|
||||
.textAlign(TextAlign.Start)
|
||||
.alignSelf(ItemAlign.Start)
|
||||
}
|
||||
.width(CommonConstants.LIST_DIALOG.ROW_WIDTH)
|
||||
.width(CommonConstants.ROW_WIDTH)
|
||||
.margin({
|
||||
top: CommonConstants.LIST_DIALOG.ROW_MARGIN_TOP,
|
||||
bottom: CommonConstants.LIST_DIALOG.ROW_MARGIN_BOTTOM
|
||||
top: CommonConstants.ROW_MARGIN_TOP,
|
||||
bottom: CommonConstants.ROW_MARGIN_BOTTOM
|
||||
})
|
||||
|
||||
List({
|
||||
space: CommonConstants.LIST_DIALOG.LIST_SPACE,
|
||||
initialIndex: CommonConstants.LIST_DIALOG.LIST_INITIAL_INDEX
|
||||
space: CommonConstants.LIST_SPACE,
|
||||
initialIndex: CommonConstants.LIST_INITIAL_INDEX
|
||||
}) {
|
||||
ForEach(this.musicList, (item: MusicItem) => {
|
||||
ListItem() {
|
||||
PlayListMusicView({ musicItem: $musicItem, item: item })
|
||||
PlayListMusicView({item: item })
|
||||
}
|
||||
}, item => JSON.stringify(item))
|
||||
}, (item: MusicItem) => JSON.stringify(item))
|
||||
}
|
||||
.listDirection(Axis.Vertical)
|
||||
.divider({
|
||||
strokeWidth: CommonConstants.LIST_DIALOG.DIVIDER_STROKE_WIDTH,
|
||||
strokeWidth: CommonConstants.DIVIDER_STROKE_WIDTH,
|
||||
color: CommonConstants.DIVIDER_COLOR,
|
||||
startMargin: CommonConstants.LIST_DIALOG.DIVIDER_START_MARGIN,
|
||||
endMargin: CommonConstants.LIST_DIALOG.END_MARGIN
|
||||
startMargin: CommonConstants.DIVIDER_START_MARGIN,
|
||||
endMargin: CommonConstants.END_MARGIN
|
||||
})
|
||||
.height(CommonConstants.LIST_DIALOG.LIST_HEIGHT)
|
||||
.width(CommonConstants.LIST_DIALOG.LIST_WIDTH)
|
||||
.height(CommonConstants.LIST_HEIGHT)
|
||||
.width(CommonConstants.LIST_WIDTH)
|
||||
}
|
||||
.width(CommonConstants.FULL_WIDTH)
|
||||
.margin({ left: CommonConstants.LIST_DIALOG.PAGE_MARGIN_LEFT })
|
||||
.margin({ left: CommonConstants.DIALOG_MARGIN_LEFT })
|
||||
}
|
||||
}
|
@ -13,29 +13,32 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { MusicItem } from '../common/bean/MusicItem';
|
||||
import { MusicItem } from '../viewmodel/MusicItem';
|
||||
import { CommonConstants } from '../common/constants/CommonConstants';
|
||||
import { PlayBarModel } from '../common/model/PlayBarModel';
|
||||
|
||||
@Component
|
||||
export struct PlayListMusicView {
|
||||
@Link musicItem: MusicItem;
|
||||
private item: MusicItem;
|
||||
@Consume playBarModel: PlayBarModel;
|
||||
private item: MusicItem = new MusicItem();
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Text(this.item.name)
|
||||
.fontSize($r('app.float.dialog_name'))
|
||||
.fontColor(this.musicItem.id === this.item.id ? $r("app.color.font_color_pink") : $r("app.color.dialog_name_color"))
|
||||
.fontColor(this.playBarModel!.musicItem!.id === this.item.id ? $r('app.color.font_color_pink') :
|
||||
$r('app.color.dialog_name_color'))
|
||||
.fontWeight(FontWeight.Normal)
|
||||
.lineHeight(CommonConstants.LIST_DIALOG_MUSIC.LINE_HEIGHT)
|
||||
.lineHeight(CommonConstants.LINE_HEIGHT)
|
||||
Row() {
|
||||
Image(this.item.isVip ? $r('app.media.ic_vip') : $r('app.media.ic_hd'))
|
||||
.width(CommonConstants.LIST_DIALOG_MUSIC.IMAGE_WIDTH)
|
||||
.height(CommonConstants.LIST_DIALOG_MUSIC.IMAGE_HEIGHT)
|
||||
.margin({ right: CommonConstants.LIST_DIALOG_MUSIC.IMAGE_MARGIN_RIGHT })
|
||||
.width(CommonConstants.LIST_IMAGE_WIDTH)
|
||||
.height(CommonConstants.LIST_IMAGE_HEIGHT)
|
||||
.margin({ right: CommonConstants.LIST_MARGIN_RIGHT })
|
||||
Text(this.item.singer)
|
||||
.fontSize($r('app.float.dialog_singer'))
|
||||
.fontColor(this.musicItem.id === this.item.id ? $r("app.color.font_color_pink") : $r("app.color.dialog_singer_color"))
|
||||
.fontColor(this.playBarModel!.musicItem!.id === this.item.id ? $r('app.color.font_color_pink') :
|
||||
$r('app.color.dialog_singer_color'))
|
||||
.fontWeight(FontWeight.Normal)
|
||||
}
|
||||
.width(CommonConstants.FULL_WIDTH)
|
||||
@ -44,8 +47,8 @@ export struct PlayListMusicView {
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
.width(CommonConstants.FULL_WIDTH)
|
||||
.margin({
|
||||
top: CommonConstants.LIST_DIALOG_MUSIC.MUSIC_MARGIN_TOP,
|
||||
bottom: CommonConstants.LIST_DIALOG_MUSIC.MUSIC_MARGIN_BOTTOM
|
||||
top: CommonConstants.LIST_MARGIN_TOP,
|
||||
bottom: CommonConstants.MUSIC_MARGIN_BOTTOM
|
||||
})
|
||||
}
|
||||
}
|
@ -15,32 +15,32 @@
|
||||
|
||||
import { CommonUtil } from '../common/utils/CommonUtil';
|
||||
import { CommonConstants } from '../common/constants/CommonConstants';
|
||||
import { PlayBarModel } from '../common/model/PlayBarModel';
|
||||
|
||||
@Component
|
||||
export struct ProgressView {
|
||||
@Link playValue: number;
|
||||
@Link totalValue: number;
|
||||
@Consume playBarModel: PlayBarModel;
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Text(CommonUtil.formatDuration(this.playValue))
|
||||
Text(CommonUtil.formatDuration(this.playBarModel.playValue))
|
||||
.fontColor($r("app.color.music_card_color"))
|
||||
.fontSize($r('app.float.dialog_singer'))
|
||||
.margin({ right: CommonConstants.PROGRESS_VIEW.TEXT_MARGIN_RIGHT })
|
||||
.margin({ right: CommonConstants.PROGRESS_MARGIN_RIGHT })
|
||||
Slider({
|
||||
value: this.playValue,
|
||||
min: CommonConstants.PROGRESS_VIEW.PROGRESS_MIN,
|
||||
max: this.totalValue,
|
||||
value: this.playBarModel.playValue,
|
||||
min: CommonConstants.PROGRESS_MIN,
|
||||
max: this.playBarModel.totalValue,
|
||||
style: SliderStyle.OutSet
|
||||
})
|
||||
.enabled(false)
|
||||
.selectedColor($r("app.color.music_card_color"))
|
||||
.layoutWeight(1)
|
||||
Text(CommonUtil.formatDuration(this.totalValue))
|
||||
Text(CommonUtil.formatDuration(this.playBarModel.totalValue))
|
||||
.fontColor($r("app.color.music_card_color"))
|
||||
.fontSize($r('app.float.dialog_singer'))
|
||||
.margin({ left: CommonConstants.PROGRESS_VIEW.TEXT_MARGIN_LEFT })
|
||||
.margin({ left: CommonConstants.PROGRESS_MARGIN_LEFT })
|
||||
}
|
||||
.margin({ top: CommonConstants.PROGRESS_VIEW.VIEW_MARGIN_TOP })
|
||||
.margin({ top: CommonConstants.VIEW_MARGIN_TOP })
|
||||
}
|
||||
}
|
54
Media/AudioPlayer/entry/src/main/ets/viewmodel/MusicItem.ets
Normal file
54
Media/AudioPlayer/entry/src/main/ets/viewmodel/MusicItem.ets
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import resourceManager from '@ohos.resourceManager';
|
||||
|
||||
/**
|
||||
* Song entity class.
|
||||
*/
|
||||
export class MusicItem {
|
||||
/**
|
||||
* Identifier.
|
||||
*/
|
||||
id: number = 0;
|
||||
/**
|
||||
* Music name.
|
||||
*/
|
||||
name: string = '';
|
||||
/**
|
||||
* Singer.
|
||||
*/
|
||||
singer: string = '';
|
||||
/**
|
||||
* Lyricist.
|
||||
*/
|
||||
lyrics: string = '';
|
||||
/**
|
||||
* Resource Path.
|
||||
*/
|
||||
path: string = '';
|
||||
/**
|
||||
* Member song or not.
|
||||
*/
|
||||
isVip: boolean = false;
|
||||
/**
|
||||
* Song icon.
|
||||
*/
|
||||
image: Resource = $r('app.media.icon');
|
||||
/**
|
||||
* Resource descriptor.
|
||||
*/
|
||||
rawFileDescriptor: resourceManager.RawFileDescriptor = {} as resourceManager.RawFileDescriptor;
|
||||
}
|
@ -13,10 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import resourceManager from '@ohos.resourceManager';
|
||||
import Logger from '../common/utils/Logger';
|
||||
import { MusicItem, MusicItemProperties } from '../common/bean/MusicItem';
|
||||
import { MusicItem } from './MusicItem';
|
||||
import { ResourceManagerUtil } from '../common/utils/ResourceManagerUtil';
|
||||
import { CommonUtil } from '../common/utils/CommonUtil';
|
||||
|
||||
/**
|
||||
* Log tag.
|
||||
@ -26,60 +26,66 @@ const TAG = '[MusicViewModel]';
|
||||
/**
|
||||
* Music data.
|
||||
*/
|
||||
const MUSIC_DATA: MusicItemProperties[] = [
|
||||
const MUSIC_DATA: MusicItem[] = [
|
||||
{
|
||||
'id': 0,
|
||||
'name': 'CLASSIC',
|
||||
'singer': 'classic',
|
||||
'lyrics': 'cl_lyrics',
|
||||
'path': 'classic.wav',
|
||||
'isVip': false,
|
||||
'image': $r('app.media.ic_music_icon')
|
||||
id: 0,
|
||||
name: 'CLASSIC',
|
||||
singer: 'classic',
|
||||
lyrics: 'cl_lyrics',
|
||||
path: 'classic.wav',
|
||||
isVip: false,
|
||||
image: $r('app.media.ic_music_icon'),
|
||||
rawFileDescriptor: {} as resourceManager.RawFileDescriptor
|
||||
},
|
||||
{
|
||||
'id': 1,
|
||||
'name': 'DYNAMIC',
|
||||
'singer': 'dynamic',
|
||||
'lyrics': 'cl_dynamic',
|
||||
'path': 'dynamic.wav',
|
||||
'isVip': false,
|
||||
'image': $r('app.media.ic_music_icon')
|
||||
id: 1,
|
||||
name: 'DYNAMIC',
|
||||
singer: 'dynamic',
|
||||
lyrics: 'cl_dynamic',
|
||||
path: 'dynamic.wav',
|
||||
isVip: false,
|
||||
image: $r('app.media.ic_music_icon'),
|
||||
rawFileDescriptor: {} as resourceManager.RawFileDescriptor
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
'name': 'FRESHNESS',
|
||||
'singer': 'freshness',
|
||||
'lyrics': 'cl_freshness',
|
||||
'path': 'freshness.wav',
|
||||
'isVip': true,
|
||||
'image': $r('app.media.ic_music_icon')
|
||||
id: 2,
|
||||
name: 'FRESHNESS',
|
||||
singer: 'freshness',
|
||||
lyrics: 'cl_freshness',
|
||||
path: 'freshness.wav',
|
||||
isVip: true,
|
||||
image: $r('app.media.ic_music_icon'),
|
||||
rawFileDescriptor: {} as resourceManager.RawFileDescriptor
|
||||
},
|
||||
{
|
||||
'id': 3,
|
||||
'name': 'LIVELY',
|
||||
'singer': 'lively',
|
||||
'lyrics': 'cl_lively',
|
||||
'path': 'lively.mp3',
|
||||
'isVip': false,
|
||||
'image': $r('app.media.ic_music_icon')
|
||||
id: 3,
|
||||
name: 'LIVELY',
|
||||
singer: 'lively',
|
||||
lyrics: 'cl_lively',
|
||||
path: 'lively.mp3',
|
||||
isVip: false,
|
||||
image: $r('app.media.ic_music_icon'),
|
||||
rawFileDescriptor: {} as resourceManager.RawFileDescriptor
|
||||
},
|
||||
{
|
||||
'id': 4,
|
||||
'name': 'NATURE',
|
||||
'singer': 'nature',
|
||||
'lyrics': 'cl_nature',
|
||||
'path': 'nature.mp3',
|
||||
'isVip': false,
|
||||
'image': $r('app.media.ic_music_icon')
|
||||
id: 4,
|
||||
name: 'NATURE',
|
||||
singer: 'nature',
|
||||
lyrics: 'cl_nature',
|
||||
path: 'nature.mp3',
|
||||
isVip: false,
|
||||
image: $r('app.media.ic_music_icon'),
|
||||
rawFileDescriptor: {} as resourceManager.RawFileDescriptor
|
||||
},
|
||||
{
|
||||
'id': 5,
|
||||
'name': 'ROMANTIC',
|
||||
'singer': 'romantic',
|
||||
'lyrics': 'cl_romantic',
|
||||
'path': 'romantic.wav',
|
||||
'isVip': false,
|
||||
'image': $r('app.media.ic_music_icon')
|
||||
id: 5,
|
||||
name: 'ROMANTIC',
|
||||
singer: 'romantic',
|
||||
lyrics: 'cl_romantic',
|
||||
path: 'romantic.wav',
|
||||
isVip: false,
|
||||
image: $r('app.media.ic_music_icon'),
|
||||
rawFileDescriptor: {} as resourceManager.RawFileDescriptor
|
||||
}
|
||||
];
|
||||
|
||||
@ -90,13 +96,14 @@ const MUSIC_DATA: MusicItemProperties[] = [
|
||||
* @param musicDataArray Music data array.
|
||||
*/
|
||||
export function initializeMusic(musicDataArray: Array<MusicItem>) {
|
||||
if (CommonUtil.isEmpty(musicDataArray)) {
|
||||
if (musicDataArray === undefined) {
|
||||
Logger.error(TAG, 'getNextMusic fail,context is empty.');
|
||||
return;
|
||||
}
|
||||
MUSIC_DATA.forEach((item) => {
|
||||
ResourceManagerUtil.getSrcPath(item.path, (value) => {
|
||||
musicDataArray.push(new MusicItem(item, value));
|
||||
MUSIC_DATA.forEach((item: MusicItem) => {
|
||||
ResourceManagerUtil.getSrcPath(item.path, (value: resourceManager.RawFileDescriptor) => {
|
||||
item.rawFileDescriptor = value;
|
||||
musicDataArray.push(item);
|
||||
Logger.info(TAG, 'ResourceManagerUtil: ' + musicDataArray.length);
|
||||
})
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"hvigorVersion": "2.1.1",
|
||||
"hvigorVersion": "2.4.2",
|
||||
"dependencies": {
|
||||
"@ohos/hvigor-ohos-plugin": "2.1.1"
|
||||
"@ohos/hvigor-ohos-plugin": "2.4.2"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user