(1)Android手機一般以客戶端的角色主動連接SPP協議設備(接上藍牙模塊的數字傳感器),連接流程是:
1.使用registerReceiver注冊BroadcastReceiver來獲取藍牙狀態、搜索設備等消息;
2.使用BlueAdatper的搜索;
3.在BroadcastReceiver的onReceive()里取得搜索所得的藍牙設備信息(如名稱,MAC,RSSI);
4.通過設備的MAC地址來建立一個BluetoothDevice對象;
5.由BluetoothDevice衍生出BluetoothSocket,准備SOCKET來讀寫設備;
6.通過BluetoothSocket的createRfcommSocketToServiceRecord()方法來選擇連接的協議/服務,這里用的是SPP(UUID:00001101-0000-1000-8000-00805F9B34FB);
7.Connect之后(如果還沒配對則系統自動提示),使用BluetoothSocket的getInputStream()和getOutputStream()來讀寫藍牙設備。
****************注意:對於UUID,必須使用Android的SSP(協議棧默認)的UUID:00001101-0000-1000-8000-00805F9B34FB才能正常和外部的,也是SSP串口的藍牙設備去連接。
(2)添加權限:
1 <uses-permission android:name="android.permission.BLUETOOTH"></uses-permission> 2 <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
(3)BluetoothAdapter類:
BluetoothAdapter類簡單點來說就是代表了本設備(手機、電腦等)的藍牙適配器對象,通過它我們可以藍牙設備進行基本開發了。
主要有如下功能:
1、開關藍牙設備
2、掃描藍牙設備
3、設置/獲取藍牙狀態信息,例如:藍牙狀態值、藍牙Name、藍牙Mac地址等;
BluetoothAdapter初始化並提示打開藍牙使用:
1 private BluetoothAdapter mBluetoothAdapter; 2 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 3 if (!mBluetoothAdapter.isEnabled()) { 4 //彈出對話框提示用戶是后打開 5 Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 6 startActivity(intent); 7 // startActivityForResult(intent, REQUEST_ENABLE); 8 //不做提示,強行打開 9 // mBluetoothAdapter.enable(); 10 }
創建監聽藍牙狀態的廣播:
1 BroadcastReceiver mFoundReceiver = new BroadcastReceiver() { 2 3 public void onReceive(Context context, Intent intent) { 4 String action = intent.getAction(); 5 //找到設備 6 if (BluetoothDevice.ACTION_FOUND.equals(action)) { 7 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 8 // 添加進一個設備列表,進行顯示。 12 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { 13 Log.v(TAG, "find device:" + device.getName() + device.getAddress()); 14 } 15 } 16 //搜索完成 17 else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { 18 cancelDiscovery();20 } 21 } 22 };
注冊廣播監聽藍牙狀態:
1 private void startDiscovery() { 5 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);//開啟搜索 6 registerReceiver(mFoundReceiver, filter); 7 filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成 8 registerReceiver(mFoundReceiver, filter);15 mBluetoothAdapter.startDiscovery();17 }
開啟和關閉藍牙掃描:
// 開啟 mBluetoothAdapter.startDiscovery(); // 關閉 mBluetoothAdapter.cancelDiscovery();
點擊掃描到的列表,傳遞點擊項的BluetoothDevice通過putExtra給藍牙數據顯示界面。
(4)進行BluetoothSocket socket 和 BluetoothDevice mBluetoothDevice 進行操作。
1 private class ConnectThread extends Thread { 2 3 public ConnectThread(BluetoothDevice device) { 4 try { 5 socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); 6 } catch (IOException e) { 7 e.printStackTrace(); 8 } 10 } 11 12 public void run() { 13 while (mAutoConnectInterruptTime < 5) { 14 try { 15 16 socket.connect(); 17 runOnUiThread(new Runnable() { 18 @Override 19 public void run() { 20 // TODO 顯示連接成功 21 } 22 }); 23 isConnect = true; 24 mAutoConnectInterruptTime = 0; 25 manageConnectedSocket(socket); // 創建新的線程對藍牙進行數據讀取。 26 break; 27 28 } catch (Exception e) { 29 e.printStackTrace(); 30 mAutoConnectInterruptTime++; 31 32 try { 33 Thread.sleep(2000); 34 } catch (InterruptedException e1) { 35 e1.printStackTrace(); 36 } 37 38 runOnUiThread(new Runnable() { 39 @Override 40 public void run() { 41 // TODO 顯示連接失敗 42 } 43 }); 44 // TODO 進行對 inputStream outputStream socket 進行關閉 置空. 45 return; 46 } 47 } 48 49 } 50 51 public void cancel() { 52 try { 53 socket.close(); 54 } catch (IOException e) { 55 e.printStackTrace(); 56 } 57 } 58 }
(5)通過BluetoothSocket socket 藍牙數據讀取:
1 public class Receive extends Thread { 2 // 變量 略過 3 4 // 構造方法 5 public Receive(BluetoothSocket socket) { 6 7 // 獲取輸入流 8 try { 9 inputStream = socket.getInputStream(); 10 outputStream = socket.getOutputStream(); 11 } catch (IOException e) { 12 e.printStackTrace(); 13 } 14 } 15 16 @Override 17 public void run() { 18 final byte[] bytes = new byte[1024];// 緩沖數據流 19 int count;// 返回讀取到的數據 20 // 監聽輸入流 21 try { 22 while (inputStream != null && (count = inputStream.read(bytes)) != -1) { 23 //獲取有效部分 24 final byte[] contents = new byte[count]; 25 for (int i = 0; i < contents.length; i++) { 26 contents[i] = bytes[i]; 27 } 28 parse(contents); // TODO 對讀取到數據進行轉換 29 } 30 } catch (Exception e) { 31 e.printStackTrace(); 32 } 33 34 ConnectThread connectBtThread = new ConnectThread(mBluetoothDevice); 35 connectBtThread.start(); 36 // TODO 進行對 inputStream outputStream socket 進行關閉 置空。 37 runOnUiThread(new Runnable() { 38 @Override 39 public void run() { 40 // TODO 關閉藍牙連接 41 } 42 }); 43 // TODO inputStream outputStream socket 進行關閉 置空 44 } 45 }
參考:
關於用到BluetoothServerSocket和BluetoothSocket兩個類來建立Server端和Client端,還需要使用到一些關於流(Stream)的知識。
- BluetoothServerSocket——服務端(監聽端、監聽器、接受請求的一端)
- Accept()——阻塞宿主線程,直至收到客戶端請求。返回BluetoothSocket對象。由於這個
- Accept(int timeout)——阻塞宿主線程,直至收到客戶端請求或等待時間超過timeout。返回BluetoothSocket對象。
- Close()——關閉BluetoothServerSocket監聽器。
可以看到,Accept方法是一個阻塞方法,所以在進行開發的時候,一般都需要用到多線程的知識。JAVA的多線程知識。
- BluetoothSocket——客戶端(請求端)
- Close()——關閉BluetoothSocket請求端。
- Connect()——主動向服務端(監聽端)發起連接請求。
可使用BluetoothAdapter類的listenUsingRfcommWithServiceRecord方法來新建一個ServerSocket。
可以使用web上的任何一款UUID產生器為你的程序獲取一個UUID,然后使用fromString(String)初始化一個UUID。
使用ServerSocket實例的accept方法進行監聽,當監聽到帶有我們初始化的UUID參數的連接請求后作出響應,連接成功后返回一個BluetoothSocket對象。連接完成后,調用close方法關閉該Socket監聽。
使用BluetoothDevice的實例的createRfcommSocketToServiceRecord方法來創建一個BluetoothSocket實例。
傳入我們服務端的UUID值。
然后使用BluetoothSocket實例的Connect方法對Server端進行連接請求,當連接成功后,Client端和Server端的傳輸通道就被打開。
參考鏈接:
Android中連接藍牙設備時遇到createRfcommSocketToServiceRecord的UUID問題和BluetoothSocket的connect失敗
http://www.cnblogs.com/cxcco/archive/2012/01/15/2322783.html
