Alarm clock FA develops alarm clock interface
Before this section, we have completed the development of the alarm clock setting FA. In this section, we will develop an interface in the alarm clock FA to display the alarm clock and a close button, and play the alarm clock sound.
1. Add an encapsulation class that plays the alarm clock sound
1.1 The code comes from the codelab distributed "HarmonyOS Distributed Video Playback", and PlayerStateListener.java and PlayerManager.java are added to encapsulate music playback. PlayerStateListener.java
package com.madixin.clock.clock.util;
/**
* PlayerStateListener
*/
public interface PlayerStateListener {
void onPlaySuccess(int totalTime);
void onPauseSuccess();
void onPositionChange(int currentTime);
void onMusicFinished();
void onUriSet(String name);
}
PlayerStateListener.java
package com.madixin.clock.clock.util;
import com.madixin.clock.common.util.LogUtil;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.global.resource.BaseFileDescriptor;
import ohos.global.resource.RawFileEntry;
import ohos.media.audio.SoundPlayer;
import ohos.media.player.Player;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
/**
* player manager
*/
public class PlayerManager {
private static final String TAG = PlayerManager.class.getSimpleName();
private static final int PLAY_STATE_PLAY = 0x0000001;
private static final int PLAY_STATE_PAUSE = 0x0000002;
private static final int PLAY_STATE_FINISH = 0x0000003;
private static final int PLAY_STATE_PROGRESS = 0x0000004;
private static final int DELAY_TIME = 1000;
private static final int PERIOD = 1000;
private Player musicPlayer;
private Context context;
private String currentUri;
private TimerTask timerTask;
private Timer timer;
private PlayerStateListener playerStateListener;
private boolean isPrepared;
public PlayerManager(Context context, String currentUri) {
this.context = context;
this.currentUri = currentUri;
}
/**
* init media resource
*/
public void init() {
musicPlayer = new Player(context);
musicPlayer.setPlayerCallback(new PlayCallBack());
setResource(currentUri);
}
/**
* set source
*
* @param uri music uri
*/
public void setResource(String uri) {
LogUtil.info(TAG, "uri: " + uri);
try {
RawFileEntry rawFileEntry = context.getResourceManager().getRawFileEntry(uri);
BaseFileDescriptor baseFileDescriptor = rawFileEntry.openRawFileDescriptor();
if (!musicPlayer.setSource(baseFileDescriptor)) {
LogUtil.info(TAG, "uri is invalid");
return;
}
isPrepared = musicPlayer.prepare();
playerStateListener.onUriSet(
currentUri.substring(currentUri.lastIndexOf("/") + 1, currentUri.lastIndexOf(".")));
} catch (IOException e) {
LogUtil.error(TAG, "io exception");
}
}
/**
* play
*/
public void play() {
if (!isPrepared) {
LogUtil.error(TAG, "prepare fail");
return;
}
if (!musicPlayer.play()) {
LogUtil.error(TAG, "play fail");
return;
}
startTask();
handler.sendEvent(PLAY_STATE_PLAY);
}
/**
* pause
*/
public void pause() {
if (!musicPlayer.pause()) {
LogUtil.info(TAG, "pause fail");
return;
}
finishTask();
handler.sendEvent(PLAY_STATE_PAUSE);
}
private EventHandler handler = new EventHandler(EventRunner.current()) {
@Override
protected void processEvent(InnerEvent event) {
switch (event.eventId) {
case PLAY_STATE_PLAY: {
playerStateListener.onPlaySuccess(getTotalTime());
break;
}
case PLAY_STATE_PAUSE: {
playerStateListener.onPauseSuccess();
break;
}
case PLAY_STATE_FINISH: {
playerStateListener.onMusicFinished();
break;
}
case PLAY_STATE_PROGRESS: {
playerStateListener.onPositionChange(musicPlayer.getCurrentTime());
break;
}
default:
break;
}
}
};
private void startTask() {
finishTask();
timerTask = new TimerTask() {
@Override
public void run() {
handler.sendEvent(PLAY_STATE_PROGRESS);
}
};
timer = new Timer();
timer.schedule(timerTask, DELAY_TIME, PERIOD);
}
private void finishTask() {
if (timer != null && timerTask != null) {
timer.cancel();
timer = null;
timerTask = null;
}
}
/**
* get duration
*
* @return total time
*/
public int getTotalTime() {
return musicPlayer.getDuration();
}
/**
* switch music
*
* @param uri music uri
*/
public void switchMusic(String uri) {
currentUri = uri;
setResource(currentUri);
play();
}
/**
* changes the playback position
*
* @param currentTime current time
*/
public void rewindTo(int currentTime) {
musicPlayer.rewindTo(currentTime * 1000);
}
/**
* release
*/
public void releasePlayer() {
if (musicPlayer == null) {
return;
}
musicPlayer.stop();
musicPlayer.release();
}
/**
* play state
*
* @return true:playing , false:pause
*/
public boolean isPlaying() {
return musicPlayer.isNowPlaying();
}
private class PlayCallBack implements Player.IPlayerCallback {
@Override
public void onPrepared() {
LogUtil.info(TAG, "onPrepared");
}
@Override
public void onMessage(int type, int extra) {
LogUtil.info(TAG, "onMessage " + type + "-" + extra);
}
@Override
public void onError(int errorType, int errorCode) {
LogUtil.info(TAG, "onError " + errorType + "-" + errorCode);
}
@Override
public void onResolutionChanged(int width, int height) {
LogUtil.info(TAG, "onResolutionChanged " + width + "-" + height);
}
@Override
public void onPlayBackComplete() {
handler.sendEvent(PLAY_STATE_FINISH);
LogUtil.info(TAG, "onPlayBackComplete");
}
@Override
public void onRewindToComplete() {
LogUtil.info(TAG, "onRewindToComplete");
}
@Override
public void onBufferingChange(int percent) {
LogUtil.info(TAG, percent + "");
}
@Override
public void onNewTimedMetaData(Player.MediaTimedMetaData mediaTimedMetaData) {
LogUtil.info(TAG, "onNewTimedMetaData");
}
@Override
public void onMediaTimeIncontinuity(Player.MediaTimeInfo mediaTimeInfo) {
LogUtil.info(TAG, "onNewTimedMetaData");
}
}
/**
* player state listener
*
* @param playerStateListener listener
*/
public void setPlayerStateListener(PlayerStateListener playerStateListener) {
this.playerStateListener = playerStateListener;
}
}
2. Develop alarm clock interface
1.1 Add a new text resource in clock>src>main>resources>base>element>string.json.
{
"name": "timeup",
"value": "到点了"
},
{
"name": "close",
"value": "关闭"
}
1.2 Add button background resource files under clock>src>main>resources>base>graphic. background_button.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:shape="rectangle">
<corners
ohos:radius="40"/>
<solid
ohos:color="#007CFD"/>
</shape>
1.3 Add button alarm clock page resource files under clock>src>main>resources>base>layout. This interface is temporarily implemented simply, only placing a TEXT and a Button control. ability_clock_alarm.xml
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:height="match_parent"
ohos:width="match_parent"
ohos:orientation="vertical">
<Text
ohos:id="$+id:text_helloworld"
ohos:height="match_content"
ohos:width="match_content"
ohos:background_element="$graphic:background_ability_clock_alarm"
ohos:layout_alignment="horizontal_center"
ohos:text="$string:timeup"
ohos:text_size="30vp"
ohos:top_margin="30fp"
/>
<Button
ohos:id="$+id:btn_close"
ohos:height="50vp"
ohos:width="match_parent"
ohos:text="$string:close"
ohos:text_size="30vp"
ohos:background_element="$graphic:background_button"
ohos:top_margin="30fp"/>
</DirectionalLayout>
1.4 Modify ClockAlarmAbilitySlice, get the alarm name through intent in the onStart method, and use PlayerManager to pull up the music. Close the current ability after clicking the close button.
package com.madixin.clock.clock.slice;
import com.madixin.clock.clock.ResourceTable;
import com.madixin.clock.clock.util.PlayerManager;
import com.madixin.clock.clock.util.PlayerStateListener;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
public class ClockAlarmAbilitySlice extends AbilitySlice {
private PlayerManager playerManager;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setUIContent(ResourceTable.Layout_ability_clock_alarm);
Button btnClose = (Button) findComponentById(ResourceTable.Id_btn_close);
btnClose.setClickedListener((button) -> {
if (playerManager.isPlaying()){
playerManager.releasePlayer();
}
this.terminate();//暂时直接关闭
});
String bell = "Canon";
if (intent != null) {
Object obj = intent.getStringParam("bell");
if (obj instanceof String) {
bell = (String) obj;
}
}
initMedia(bell);
}
@Override
public void onActive() {
super.onActive();
}
@Override
public void onForeground(Intent intent) {
super.onForeground(intent);
}
private void initMedia(String bell) {
playerManager = new PlayerManager(this, "resources/rawfile/" + bell + ".mp3");
playerManager.setPlayerStateListener(new PlayerStateListener() {
@Override
public void onPlaySuccess(int totalTime) {
}
@Override
public void onPauseSuccess() {
}
@Override
public void onPositionChange(int currentTime) {
}
@Override
public void onMusicFinished() {
}
@Override
public void onUriSet(String name) {
}
});
playerManager.init();
playerManager.play();
}
}
3. Summary
At the end of this chapter, the development of the alarm clock interface is completed in the alarm clock FA.
In the next step, we will add a regularly called PA to the FA clock in the alarm clock setting, pull up the alarm clock interface, and realize that after clicking Close, the FA will be automatically closed and the status of the PA will be modified.
4. Code address:
github , commit record: c90f87e2928993d1e197e00220f8bd708eaeacd6