用Android 開發一個應用,其中想使用藍牙來做資料交換。

先查了一下資料,感覺還算簡單,於是就開始了一整天的痛苦歷程。


基本上用discover之類的能夠很快的發現對方的藍牙設備,但是在

建立socket的時候,就出了一堆問題。剛開始,服務端用


adapter.listenUsingRfcommWithServiceRecord


加上某個UUID來監聽,同時獲得serverSocket,用戶端用


serverDevice.createRfcommSocketToServiceRecord


來獲取socket,然後就在 socket.connect的時候,出了很多

奇怪的錯誤。


最開始是 Service discovery failed ,

然後是 connection refused,

然後是 File descriptor in bad state


總之搜索了一下,確實千奇百怪的錯誤都有。後來看到有人用



Method m = serverDevice.getClass().getMethod( "createRfcommSocket", new Class[]{int.class});

BluetoothSocket socket = (BluetoothSocket) m.invoke( serverDevice, Integer.valueOf( 1));



據說能解決,嘗試了一下,也是有時成功有時失敗,極不穩定。


再後來,仔細考慮了一下,其實 createRfcommSocket 這個方法,指定連接的是 1號埠,
而服務端則還是用UUID來啟動服務,至於其綁定了哪個埠,其實是不可知的。
最開始用戶端用 createRfcommSocketToServiceRecord 這個方法,其實是利用UUID去找到
相應的服務,只不過不知道是不是我的UUID的問題,導致它找不到,所以報 service discovery failed這個錯。
而直接用反射的方法去訪問 1號埠,如果湊巧服務端也是在1號埠監聽,那就沒問題。如果不是,
並且沒有服務在監聽,就會報connection refused這個錯。如果有別的服務在監聽,然後又不理解
我的這個協定,就會報 File descriptor in bad state 這個錯。


想明白了,解決起來也就容易。辦法是在啟動服務的時候,也用反射


Method listenMethod = btClass.getMethod("listenUsingRfcommOn", new Class[]{int.class});
BluetoothServerSocket returnValue = ( BluetoothServerSocket) listenMethod.invoke(btAdapter, new Object[]{ 29});


我在伺服器和用戶端都用29埠,然後就穩定下來了。
花了一整天的時間,真是無語。
創作者介紹
創作者 shadow 的頭像
shadow

資訊園

shadow 發表在 痞客邦 留言(0) 人氣()