直接回答
理論上可行,實際上極難落地。 標準 API 存在(JSR 177 SATSA),但 2000 年代末至 2010 年代初主流商用手機幾乎無裝置實作此規格。
技術規範:SATSA (Security and Trust Services API for J2ME, JSR 177)
核心 API 入口
// 建立 SIM 卡連線 (概念性程式碼,實際 API 較複雜)
SATSAConnector.open("satsa://sim?slot=0"); // 類似 GCF 連接字串
// 發送 APDU 指令讀取 EF 文件 (如 IMSI、電話簿、短訊)
byte[] response = apduConnection.exchange(apduCommand);
三大落地阻礙
| 阻礙 | 說明 |
| 裝置支援率極低 | 手機廠商基於安全/成本/法規考量,未在商用韌體實作 SATSA。即使支援 Java Card 平台,SIM 應用通常由營運商 OTA 下載,非 MIDlet 直接存取 |
| 權限模型嚴格 | 存取 SIM 需 MIDlet-Permissions: javax.microedition.securityservice.SATSA,屬高風險權限,極難通過簽名審核 |
| JSR 118 規範衝突 | 若嘗試自簽名繞過,違反「出廠後安裝根憑證不可驗證 MIDlet」規定,真機會拒絕安裝 |
替代方案與變通
- 等待支援裝置:不切實際,產業已轉向 Android/iOS
- 嵌入 SATSA 類別庫並 ProGuard 混淆:
SATSA classes override CLDC and MIDP classes,需混淆避免衝突。但底層 Native 實作缺失,API 呼叫仍會拋 UnsatisfiedLinkError 或 SecurityException
- 伺服器端代理:應用上傳用戶授權資訊至伺服器,由伺服器與營運商核心網交互(USSD/SS7/HTTPS API)查詢 SIM 相關資料,再回傳結果
- USSD 代碼:撥號介面輸入
*#06# (IMEI)、*100# (餘額) 等 USSD 代碼,透過 platformRequest("tel:*100#") 唤起系統處理(需裝置支援)
現代映照:Android/iOS 如何處理 SIM 存取