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

MIDP 2.0 Push Registry 機制完整指南:自動啟動與訊息驅動

     編輯:J2ME

MIDP 2.0 引入 PushRegistry 類別,允許 MIDlet 透過定時鬧鐘或入站網路連線 (SMS、Socket、Datagram) 自動啟動。這讓應用能處理排程同步、即時推播等進階場景,無需使用者手動啟動。

核心概念

  • Alarm (鬧鐘):指定時間自動啟動 MIDlet
  • Connection (連線):收到 SMS、Socket 或 Datagram 封包觸發啟動
  • AMS (Application Management Software):管理 Push 註冊、監聽觸發條件、啟動 MIDlet

PushRegistry 關鍵 API

// 動態註冊 (執行時)
static String registerAlarm(String midlet, long time); // 毫秒時間戳
static void registerConnection(String connection, String midlet, String filter);
static void unregisterConnection(String connection);

// 靜態查詢
static String[] listConnections(boolean available);
static String getMIDlet(String connection);
static String getFilter(String connection);
static long listConnections(String midlet); // 註冊的鬧鐘時間

連線類型與 URL 格式

類型URL 格式說明
SMSsms://:port所有 Motorola、多數 Nokia 支援
TCP Socketsocket://:port理論支援,實機罕見
UDP Datagramdatagram://:port2005 後期機型支援 (V3X、E1070 等)

保留埠號 (不可註冊)


// WAP/OTA/SyncML 相關保留埠
2805, 2923, 2948, 2949, 5502, 5503, 5508, 5511, 5512,
9200, 9201, 9202, 9203, 9207, 49996, 49999
// 完整清單請參考 JSR 120 附錄 A.6.0

動態註冊範例

public class PushDemoMIDlet extends MIDlet {
    private static final int SMS_PORT = 50000;
    private static final int DATAGRAM_PORT = 50001;

    protected void startApp() {
        // 註冊 SMS Push
        try {
            PushRegistry.registerConnection(
                "sms://:" + SMS_PORT, 
                this.getClass().getName(), 
                "*"  // 接受所有發送者
            );
        } catch (Exception e) { e.printStackTrace(); }

        // 註冊 Datagram Push (若裝置支援)
        try {
            PushRegistry.registerConnection(
                "datagram://:" + DATAGRAM_PORT,
                this.getClass().getName(),
                "*"
            );
        } catch (Exception e) { /* 忽略不支援 */ }

        // 排程 1 小時後自動啟動
        scheduleAlarm(60 * 60 * 1000);
    }

    private void scheduleAlarm(long delayMs) {
        try {
            long alarmTime = System.currentTimeMillis() + delayMs;
            long registered = PushRegistry.registerAlarm(
                this.getClass().getName(), alarmTime);
            System.out.println("Alarm registered at: " + new Date(registered));
        } catch (Exception e) { e.printStackTrace(); }
    }

    protected void destroyApp(boolean unconditional) {
        // 清理資源後重新排程
        scheduleAlarm(DEFAULT_INTERVAL);
    }
}

靜態註冊 (JAD 檔)

MIDlet-Name: PushDemo
MIDlet-Version: 1.0
MIDlet-Vendor: Example
MIDlet-1: PushDemo,,PushDemoMIDlet
MicroEdition-Configuration: CLDC-1.1
MicroEdition-Profile: MIDP-2.0

# SMS Push 靜態註冊
MIDlet-Push-1: sms://:50000, PushDemoMIDlet, *

# Datagram Push 靜態註冊
MIDlet-Push-2: datagram://:50001, PushDemoMIDlet, *

# IP 過濾器支援通配符
MIDlet-Push-3: socket://:6000, PushDemoMIDlet, 192.168.1.*

啟動時判斷觸發來源

protected void startApp() {
    String[] connections = PushRegistry.listConnections(true);
    
    if (connections == null || connections.length == 0) {
        // 使用者手動啟動
        showMainMenu();
    } else {
        // 由 Push 觸發啟動
        for (String conn : connections) {
            if (conn.startsWith("sms://")) {
                handleSMSPush(conn);
            } else if (conn.startsWith("datagram://")) {
                handleDatagramPush(conn);
            } else if (conn.startsWith("socket://")) {
                handleSocketPush(conn);
            }
        }
    }
}

private void handleSMSPush(String connUrl) {
    try {
        MessageConnection msgConn = (MessageConnection) Connector.open(connUrl);
        Message msg = msgConn.receive();
        if (msg instanceof TextMessage) {
            String text = ((TextMessage) msg).getPayloadText();
            processCommand(text);
        }
        msgConn.close();
    } catch (IOException e) { e.printStackTrace(); }
}

觸發行為矩陣

狀況AMS 行為
MIDlet 正在執行,收到 Push忽略觸發,MIDlet 繼續執行 (需自行處理連線)
MIDlet 未執行,收到 Push自動啟動 MIDlet
其他 MIDlet 執行中,收到 Push詢問使用者是否切換 (同意則終止當前 MIDlet)
多個 Push 訊息排隊最多佇列 5 個,依序處理
無對應註冊忽略訊息

常見例外處理

  • ConnectionNotFoundException:協定/埠不支援
  • SecurityException:權限不足 (需簽名或使用者授權)
  • IllegalArgumentException:URL 格式錯誤或埠號保留
  • ClassNotFoundException:MIDlet 類別名稱錯誤

實務應用場景

  • 📱 即時通訊:收到 SMS 啟動,再建立 Socket 連線同步訊息
  • 🔄 定時同步:每日固定時間自動啟動上傳資料/下載更新
  • 📍 位置回報:伺服器透過 SMS 喚醒客戶端回報 GPS 座標
  • 🔔 行銷推播:新優惠/新聞透過 Datagram 唤醒顯示通知

最佳實務

  • ✅ 優先使用 SMS Push (相容性最佳)
  • ✅ 動態註冊配合靜態註冊雙重保障
  • ✅ 啟動時必檢查 listConnections(true) 判斷觸發來源
  • ✅ 妥善關閉 MessageConnection 釋放埠口
  • ✅ 鬧鐘時間使用 System.currentTimeMillis() 絕對時間
  • ✅ destroyApp() 中重新排程下次鬧鐘
  • ✅ 測試時注意:模擬器 Push 行為與真機可能不同

善用 Push Registry,您的 J2ME 應用將具備「隨時在線」的感知能力,大幅提升使用者體驗與應用價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved