企業級移動應用需求:服務器主動推送數據到手機,**無需用戶手動啟動**,自動喚醒已安裝的 MIDlet 進行業務處理(如工單派發、緊急通知、即時競價)。
MIDP 2.0 (JSR 118) 引入 **Push Registry** 機制,配合 SMS (WMA 1.1 支持) 實現「無 IP、無長連接」的可靠喚醒。
MIDlet-Push-<n>: <ConnectionURL>, <MIDletClassName>, <AllowedSender>PushRegistry.listConnections(true)MIDlet-Push-1: sms://:5000, com.example.AlertMidlet, *
MIDlet-Push-2: socket://:7777, com.example.SocketMidlet, 13800138000
sms://:5000:監聽端口 5000 的 SMS (WMA 標準)*:允許任意發送者;可限制具體號碼提升安全性| 維度 | Socket Push | SMS Push |
|---|---|---|
| 目標定址 | 需知手機無線 IP (動態、NAT、防火牆難題) | 只需手機號 (公網唯一、穩定) |
| 設備在線要求 | 需保持長連接/心跳 (耗電、易斷) | 無需數據連接,僅需信號覆蓋 |
| 設備支持度 | 所有 MIDP 2.0 必須支持 | 需 WMA 1.1 可選包支持 (主流機型均支持) |
| 成本 | 數據流量費 | 短信費 (企業批量通道較低) |
import javax.microedition.midlet.*;
import javax.microedition.io.*;
import javax.wireless.messaging.*;
public class AlertMidlet extends MIDlet implements CommandListener {
private Display display;
private Form alertForm;
private Command exitCmd;
protected void startApp() {
if (display == null) {
display = Display.getDisplay(this);
exitCmd = new Command("退出", Command.EXIT, 1);
alertForm = new Form("服務器推送");
alertForm.addCommand(exitCmd);
alertForm.setCommandListener(this);
}
// 處理 Push 啟動傳入的連接
String[] connections = PushRegistry.listConnections(true);
for (String conn : connections) {
try {
MessageConnection mc = (MessageConnection) Connector.open(conn);
Message msg = mc.receive(); // 阻塞讀取
if (msg instanceof TextMessage) {
String text = ((TextMessage) msg).getPayloadText();
alertForm.append("收到推送: " + text + "\n");
}
mc.close();
} catch (IOException e) { e.printStackTrace(); }
}
display.setCurrent(alertForm);
}
protected void pauseApp() {}
protected void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable d) {
if (c == exitCmd) {
notifyDestroyed();
}
}
}
import org.smslib.*;
public class SMSSender {
public static void sendPush(String phone, int port, String text) throws Exception {
SerialModemGateway gateway = new SerialModemGateway("modem.com1", "COM1", 115200, "Nokia", "6600");
gateway.setInbound(true);
gateway.setOutbound(true);
gateway.setSimPin("0000"); // 如有 PIN
Service.getInstance().addGateway(gateway);
Service.getInstance().startService();
OutboundMessage msg = new OutboundMessage(phone, text);
msg.setPort(port); // 關鍵:設置目標端口,觸發 Push Registry
msg.setEncoding(Message.MessageEncodings.ENC7BIT); // 或 UCS2 中文
Service.getInstance().sendMessage(msg);
System.out.println("發送成功: " + msg.getRefNo());
Service.getInstance().stopService();
}
}
Java ME (J2ME) 已退出歷史舞台。現代移動推送請使用:
但理解 Push Registry「無 IP 喚醒、協議解耦、端口多路復用」的設計思想,對設計現代推送系統依然極具啟發價值。