鸿蒙应用:多设备闹钟开发教程(7)

闹钟FA开发闹钟界面

本节之前,我们已经完成了闹钟设置FA的开发。本节我们将在闹钟FA开发一个界面显示闹钟和一个关闭按钮,并播放闹钟声音。

1.添加播放闹钟声音的封装类

1.1 代码来自codelab分布式“HarmonyOS 分布式视频播放”,新增PlayerStateListener.java和PlayerManager.java封装音乐播放。 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.开发闹钟界面

1.1 在clock>src>main>resources>base>element>string.json中添加新的文字资源。

    {
      "name": "timeup",
      "value": "到点了"
    },
    {
      "name": "close",
      "value": "关闭"
    }

1.2 在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 在clock>src>main>resources>base>layout下添加按钮闹钟页面资源文件。这个界面暂时简单实现,仅放置一个TEXT和一个Button控件。 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 修改ClockAlarmAbilitySlice,在onStart方法中通过intent获取闹铃名称,使用PlayerManager拉起音乐。点击关闭按钮后关闭当前ability。

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.小结

本章完在闹钟FA里完成了闹钟界面的开发。

下一步我们将在闹钟设置FA钟增加一个定时调用的PA,拉起闹钟界面,并实现点击关闭后,自动关闭FA以及修改PA的状态。

4.代码地址:

github,提交记录:c90f87e2928993d1e197e00220f8bd708eaeacd6

猜你喜欢

转载自blog.csdn.net/sd2131512/article/details/117572356
今日推荐