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

J2ME WMA 短信發送實戰:TextMessage 完整流程與錯誤處理模式

     編輯:J2ME

三大發送短信架構對比

方式原理優點缺點適用場景
伺服器網關App → HTTP → 運營商 SMPP/HTTP 閘道 → 手機成本可控、支援長短信、狀態報告、國際發送需伺服器開發/租用、網絡延遲商業營銷、驗證碼、通知系統
PC 數據線 + AT 指令PC 程式 → USB/藍牙 → 手機 Modem → AT+CMGS免費(含套餐)、直接用手機卡需實體連接、阻塞手機、跨平台難個人工具、測試、小規模發送
手機端 J2ME (WMA)MIDlet → WMA API → 手機基帶 → 基站無伺服器、用戶感知透明、可整合遊戲邏輯受手機權限限制、可能彈出確認框、計費不可控遊戲邀請、分享分數、社交功能

WMA (Wireless Messaging API) 架構

  • JSR 120 (WMA 1.0):MIDP 1.0 選配,支援 SMS 文本/二進制、CBS (小區廣播)。
  • JSR 205 (WMA 2.0):MIDP 2.0 內建,新增 MMS、多段短信、狀態報告監聽。
  • 核心類:javax.wireless.messaging.MessageConnection, TextMessage, BinaryMessage。

標準發送流程


import javax.wireless.messaging.*;
import javax.microedition.io.*;

public class SmsSender {
    // 發送文本短信
    // @return true 發送請求已提交給基帶 (不保證對方收到)
    public static boolean sendText(String phoneNumber, String content) {
        MessageConnection conn = null;
        try {
            // 1. 目標地址: sms://+國碼號碼 (國際格式最相容)
            String addr = "sms://+" + phoneNumber.trim();
            
            // 2. 開啟連線 (非阻塞,快速返回)
            conn = (MessageConnection) Connector.open(addr);
            
            // 3. 建立文本訊息
            TextMessage msg = (TextMessage) conn.newMessage(
                MessageConnection.TEXT_MESSAGE);
            
            // 4. 設定內容 (自動處理 7-bit/8-bit/UCS-2 編碼)
            msg.setPayloadText(content);
            
            // 5. 發送 (非同步,立即返回)
            conn.send(msg);
            return true;
            
        } catch (Exception e) {
            // 常見異常: SecurityException(權限), IOException(無信號/格式錯誤), 
            // IllegalArgumentException(號碼格式)
            return false;
        } finally {
            if (conn != null) try { conn.close(); } catch (IOException ignored) {}
        }
    }
}

權限與安全模型 (關鍵)

建議:遊戲社交功能預期用戶主動觸發 (按「邀請好友」),Untrusted 域下確認框可接受;自動發送 (如心跳) 需簽名。

進階:長短信與多段發送 (WMA 2.0)


// WMA 2.0 自動分段,開發者無感知
// 若需手動控制或讀取段數:
public static int getSegmentCount(String content) {
    // 7-bit 編碼: 160 字/段, 中文 UCS-2: 70 字/段
    // 簡易估算:
    boolean hasChinese = content.matches(".*[\\u4e00-\\u9fa5].*");
    int perSeg = hasChinese ? 70 : 160;
    return (content.length() + perSeg - 1) / perSeg;
}

完整錯誤處理與重試模式


public class RobustSmsSender {
    private static final int MAX_RETRY = 3;
    private static final int RETRY_DELAY_MS = 2000;

    public static boolean sendWithRetry(String phone, String text, SmsCallback cb) {
        new Thread(() -> {
            for (int attempt = 1; attempt <= MAX_RETRY; attempt++) {
                try {
                    if (sendText(phone, text)) {
                        cb.onSuccess();
                        return;
                    }
                } catch (Exception e) {
                    // 記錄日誌
                }
                if (attempt < MAX_RETRY) {
                    try { Thread.sleep(RETRY_DELAY_MS * attempt); } 
                    catch (InterruptedException ignored) {}
                }
            }
            cb.onFailed("超過重試次數");
        }).start();
        return true; // 非同步啟動
    }

    interface SmsCallback {
        void onSuccess();
        void onFailed(String reason);
    }
}

接收短信 (雙向通訊)


// 需在 JAD 註冊 Push Registry
// MIDlet-Push-1: sms://:5000, com.mygame.SmsMidlet, *

public class SmsReceiver extends MIDlet implements MessageListener {
    private MessageConnection conn;

    protected void startApp() {
        try {
            conn = (MessageConnection) Connector.open("sms://:5000");
            conn.setMessageListener(this);
        } catch (IOException e) { /* 處理 */ }
    }

    public void notifyIncomingMessage(MessageConnection conn) {
        // 在獨立執行緒回調,可直接處理
        new Thread(() -> {
            try {
                Message msg = conn.receive();
                if (msg instanceof TextMessage) {
                    String from = msg.getAddress(); // 發送者號碼
                    String text = ((TextMessage) msg).getPayloadText();
                    processIncomingSms(from, text);
                }
            } catch (IOException ignored) {}
        }).start();
    }
    // ...
}

最佳實踐清單

  1. ✅ 號碼統一用國際格式 +86138xxxxxxxx (去除空格/連字符)。
  2. ✅ 發送前驗證號碼格式 (正則 ^\\+?[1-9]\\d{6,14}$)。
  3. ✅ 內容長度預檢,超長提示用戶或自動截斷。
  4. ✅ 非同步發送 + 回調,不阻塞 UI 執行緒。
  5. ✅ 捕獲 SecurityException 友善提示「需授權發送短信」。
  6. ✅ 真機測試不同運營商/機型確認框行為差異。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
安全域短信發送行為
Untrusted (未簽名/自簽)每次發送彈出用戶確認對話框「允許發送短信嗎?」,用戶可拒絕。
Trusted (CA 簽名)首次安裝提示授權,後續靜默發送 (視運營商策略)。
Manufacturer/Operator完全靜默,無提示。