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

Java ME 藍牙裝置發現與 OBEX 檔案傳輸實作全攻略

     編輯:Java 相關知識

在 Java ME (Micro Edition) 平台上開發藍牙應用,核心流程包含三大階段:裝置發現、服務搜尋、資料傳輸。本文將透過一個完整的 MIDlet 範例,詳細解析如何利用 JSR 82 API 實現裝置配對、尋找 OBEX Push 服務,並傳送文字訊息到目標裝置(如支援藍牙的 Windows Vista 筆電)。

開發環境與前置需求

  • Java ME SDK / WTK (Wireless Toolkit)
  • 支援 JSR 82 (Bluetooth API) 的實體手機或模擬器(文中以 Nokia N95 實測)
  • 目標裝置需開啟藍牙並設為「可被發現」模式

第一階段:啟動裝置發現

發現流程的起點是取得本地藍牙裝置的 DiscoveryAgent,並啟動查詢:

// 取得本地發現代理
DiscoveryAgent agent = LocalDevice.getLocalDevice().getDiscoveryAgent();

// 開始一般無限制查詢 (GIAC),this 實作 DiscoveryListener 接收回呼
agent.startInquiry(DiscoveryAgent.GIAC, this);

DiscoveryListener 介面需實作四個方法,其中兩個對發現階段關鍵:

  • deviceDiscovered(RemoteDevice btDevice, DeviceClass cod):發現新裝置時觸發,此處將裝置友善名稱加入 UI 列表,並以雜湊表對應索引與裝置物件。
  • inquiryCompleted(int discType):查詢結束,根據結果更新顯示(裝置列表或「無裝置」提示)。

第二階段:搜尋目標服務 (OBEX Push)

找到裝置後,必須查詢其支援的服務。為了傳送檔案,我們尋找 OBEX Object Push Profile,其 UUID 為 0x1105:

// 針對特定裝置搜尋 OBEX Push 服務
agent.searchServices(
    null,                          // 不指定屬性集合
    new UUID[] { new UUID(0x1105L) }, // 目標服務 UUID
    remoteDevice,                  // 目標裝置
    this                           // DiscoveryListener 回呼
);

服務發現完成時,servicesDiscovered(int transID, ServiceRecord[] servRecord) 會被呼叫。關鍵步驟是從 ServiceRecord 取得連線 URL:

// 取得無需認證/加密的連線 URL
String connURL = servRecord[i].getConnectionURL(
    ServiceRecord.NOAUTHENTICATE_NOENCRYPT, 
    false
);

此 URL 封裝了協定、目標裝置位址、通道號等資訊,是後續建立連線的關鍵。

第三階段:透過 OBEX PUT 傳送資料

拿到連線 URL 後,即可建立 ClientSession 並推送資料:

// 1. 開啟用戶端會話
ClientSession clientSession = (ClientSession) Connector.open(connURL);

// 2. 連線 (無標頭)
HeaderSet connectReply = clientSession.connect(null);
if (connectReply.getResponseCode() != ResponseCodes.OBEX_HTTP_OK) {
    throw new IOException("連線失敗,回應碼:" + connectReply.getResponseCode());
}

// 3. 準備傳輸標頭
HeaderSet headers = clientSession.createHeaderSet();
headers.setHeader(HeaderSet.LENGTH, new Long(message.length()));
headers.setHeader(HeaderSet.NAME, "myNote.txt");
headers.setHeader(HeaderSet.TYPE, "text/plain");

// 4. 建立 PUT 操作並寫入資料
Operation putOp = clientSession.put(headers);
OutputStream out = putOp.openOutputStream();
out.write(message.getBytes());
out.close();
putOp.close();
clientSession.disconnect(null);

注意事項:

  • 首次配對時,目標裝置會跳出確認對話框,可能要求輸入 PIN 碼。
  • 接收端檔案通常存放在「藍牙接收資料夾」或「我的文件/Bluetooth」下。
  • 傳輸大檔案時建議分塊寫入,並處理 InterruptedIOException。

完整 MIDlet 結構概覽

public class BluetoothChatMIDlet extends MIDlet implements DiscoveryListener, CommandListener {
    // UI 元件: List (裝置列表), TextBox (輸入訊息), Alert/Form (狀態顯示)
    // 狀態機: IDLE -> INQUIRING -> SERVICE_SEARCH -> CONNECTING -> SENDING
    // 核心欄位: DiscoveryAgent agent, Hashtable devices, Vector foundServices, String connURL
    
    // 實作 DiscoveryListener 4 個方法
    // 實作 CommandListener 處理使用者操作 (搜尋、傳送、離開)
    // 內部類別 SenderThread 執行實際 OBEX 傳輸避免阻塞 UI 執行緒
}

實戰除錯提示

現象可能原因解決方向
startInquiry 擲出 BluetoothStateException藍牙關閉或硬體不支援檢查 LocalDevice.getLocalDevice() 是否拋出例外;確認手機藍牙已開啟
搜尋不到服務目標裝置未開啟 OBEX Push / 可被發現模式Windows:「控制台 > 藍牙裝置 > 選項 > 開啟傳入連線」;手機:開啟「接收檔案」模式
連線逾時 / ConnectionNotFoundExceptionURL 格式錯誤、通道號不對、防火牆阻擋印出 connURL 檢查格式;嘗試 NOAUTHENTICATE_NOENCRYPT 降低安全性需求
傳送中斷訊號弱、目標裝置儲存空間不足、對方取消接收捕獲 IOException 並給予使用者友善提示;大檔案分段傳輸

總結與延伸

掌握「發現 → 服務搜尋 → OBEX 傳輸」三部曲,即可構建基礎的 Java ME 藍牙傳檔應用。進階方向可包含:

  • 實作 OBEX FTP 以瀏覽/管理遠端檔案系統
  • 整合 RFCOMM 開發自訂協定的聊天室或遠端控制
  • 加入 安全配對 (Authentication/Encryption) 流程
  • 支援背景傳輸與斷點續傳

雖然 Java ME 已漸退出歷史舞台,但 JSR 82 的設計思維(裝置/服務/連線三層抽象)對理解現代 Android 藍牙 API (BluetoothAdapter, BluetoothDevice, BluetoothSocket) 仍有極高參考價值。

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