首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> J2ME

J2ME DateField 定時鬧鐘完整實現

     編輯:J2ME

效果演示

用戶通過 DateField (DATE_TIME) 選擇未來時間點,點擊「Snooze」啟動定時器,到時彈出 Alert (ALARM) 並播放系統提示音。

完整源碼

import java.util.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class Snooze extends MIDlet implements ItemStateListener, CommandListener {
    private Display display;
    private Form form;
    private Command cmdSnooze, cmdReset, cmdExit;
    private DateField dfTime;
    private int dateIndex;
    private Date currentTime;
    private Timer timer;
    private TimerTask task;
    private boolean dateValid = false;

    public Snooze() {
        display = Display.getDisplay(this);
        form = new Form("設定鬧鐘時間:");
        currentTime = new Date();

        dfTime = new DateField("", DateField.DATE_TIME);
        dfTime.setDate(currentTime);

        cmdSnooze = new Command("啟動", Command.SCREEN, 1);
        cmdReset  = new Command("重置", Command.SCREEN, 2);
        cmdExit   = new Command("退出", Command.EXIT, 1);

        dateIndex = form.append(dfTime);
        form.addCommand(cmdSnooze);
        form.addCommand(cmdReset);
        form.addCommand(cmdExit);
        form.setCommandListener(this);
        form.setItemStateListener(this);
    }

    protected void startApp() { display.setCurrent(form); }
    protected void pauseApp() {}
    protected void destroyApp(boolean u) { cancelTimer(); }

    public void itemStateChanged(Item item) {
        if (item == dfTime) {
            Date selected = dfTime.getDate();
            dateValid = (selected != null && selected.getTime() > currentTime.getTime());
        }
    }

    public void commandAction(Command c, Displayable d) {
        if (c == cmdSnooze) {
            if (!dateValid) {
                showError("時間無效", "請選擇當前時間之後的日期");
                return;
            }
            startTimer();
        } else if (c == cmdReset) {
            currentTime = new Date();
            dfTime.setDate(currentTime);
            dateValid = false;
        } else if (c == cmdExit) {
            destroyApp(false);
            notifyDestroyed();
        }
    }

    private void startTimer() {
        cancelTimer();
        long delay = dfTime.getDate().getTime() - currentTime.getTime();
        timer = new Timer();
        task = new TimerTask() {
            public void run() {
                Alert al = new Alert("時間到!");
                al.setType(AlertType.ALARM);
                al.setTimeout(Alert.FOREVER);
                AlertType.ALARM.playSound(display);
                display.setCurrent(al);
                cancelTimer();
            }
        };
        timer.schedule(task, delay);

        // UI 切換為倒計時狀態
        form.removeCommand(cmdSnooze);
        form.removeCommand(cmdReset);
        form.delete(dateIndex);
        form.setTitle("倒計時中...");
    }

    private void cancelTimer() {
        if (task != null) { task.cancel(); task = null; }
        if (timer != null) { timer.cancel(); timer = null; }
    }

    private void showError(String title, String msg) {
        Alert al = new Alert(title, msg, null, AlertType.ERROR);
        al.setTimeout(Alert.FOREVER);
        display.setCurrent(al, form);
    }
}

關鍵技術點

  1. DateField.DATE_TIME:同時選擇日期與時間,返回 java.util.Date (毫秒精度)。
  2. ItemStateListener:監聽用戶修改 DateField,即時校驗是否早於當前時間。
  3. Timer + TimerTask:CLDC 1.1 / MIDP 2.0 標準定時機制,schedule(task, delayMs) 單次觸發。
  4. AlertType.ALARM.playSound(display):播放系統預設鬧鐘鈴聲,無需 MMAPI。
  5. 生命週期管理:destroyApp / pauseApp 中取消定時器,防止 MIDlet 暫停/銷毀後仍觸發。

常見坑點

  • 模擬器時間與系統時間不同步:部分 WTK 模擬器 DateField 初始時間為 1970/01/01,需手動 setDate(new Date())。
  • 延遲超過 Integer.MAX_VALUE (≈24 天):Timer.schedule 參數為 long,但部分實現內部轉 int 會溢位。長延遲請分段排程或用 System.currentTimeMillis() 輪詢。
  • 真機省電模式導致 Timer 不準:手機進入深度睡眠可能暫停 Timer,關鍵鬧鐘建議結合 Push Registry (JSR 118) 實現系統級喚醒。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved