android 蓝牙学习笔记

蓝牙部分学习
蓝牙之间的通信需要四部分:
1 设置蓝牙设备
BluetoothDevice类:本地蓝牙适配器,可以发现蓝牙设备,查询帮定的设备,
使用已知的MAC地址实例化一个蓝牙设备建立一个 BluetoothServerSocket
BluetoothDevice: 远端的蓝牙设备,使用它请求远端蓝牙设备连接或是取得远端蓝牙设备的一些属性(其信息封装在bluetoothsocket中)
bluetoothsocket: 蓝牙的套接字接口
Bluetoothserversocket:打开服务连接来监听可能到来的请求
Bluttoothclass: 描述一个蓝牙设备的一般特点和能力
2 寻找设备
3 连接设备
4 设备之间的数据传输






具体编程实现
1 启动蓝牙
在构造器中取得蓝牙造配器
BluetoothAdapter mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
查询蓝牙设备的状态(打开)
if( mBluetoothAdapter.isEnabled()){
Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent,REQUEST_ENABLE_BT);

}
2 查找设备
3 查询已配对设备
1 Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();2 // If there are paired devices3 if (pairedDevices.size() > 0) {4 //Loop through paired devices5 for (BluetoothDevice device : pairedDevices) {6 // Add the name and address to an array adapter to show in a ListView7 mArrayAdapter.add(device.getName() + "\n" + device.getAddress());8 }9 }

4 扫描设备
1 // Create a BroadcastReceiver for ACTION_FOUND 2 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 3 public void onReceive(Context context, Intent intent) { 4 String action = intent.getAction(); 5 // When discovery finds a device 6 if (BluetoothDevice.ACTION_FOUND.equals(action)) { 7 // Get the BluetoothDevice object from the Intent 8 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 9 // Add the name and address to an array adapter to show in a ListView10 mArrayAdapter.add(device.getName() + "\n" + device.getAddress());11 }12 }13 };14 15 // Register the BroadcastReceiver16 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);17 registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy

5 使能被发现
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);2 discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);3 startActivity(discoverableIntent);
6. 连接设备:


  在应用程序中,想建立两个蓝牙设备之间的连接,必须实现客户端和服务器端的代码(因为任何一个设备都必须可以作为服务端或者客户端)。一个开启服务来监听,一个发起连接请求(使用服务器端设备的MAC地址)。当他们都拥有一个蓝牙套接字在同一RFECOMM信道上的时候,可以认为他们之间已经连接上了。服务端和客户端通过不同的方式或其他们的蓝牙套接字。当一个连接监听到的时候,服务端获取到蓝牙套接字。当客户可打开一个FRCOMM信道给服务器端的时候,客户端获取到蓝牙套接字。


  注意:在此过程中,如果两个蓝牙设备还没有配对好的,android系统会通过一个通知或者对话框的形式来通知用户。RFCOMM连接请求会在用户选择之前阻塞。如下图:





7. 服务端的连接:


  当你想要连接两台设备时,一个必须作为服务端(通过持有一个打开的BluetoothServerSocket),目的是监听外来连接请求,当监听到以后提供一个连接上的BluetoothSocket给客户端,当客户端从BluetoothServerSocket得到BluetoothSocket以后就可以销毁BluetoothServerSocket,除非你还想监听更多的连接请求。


  建立服务套接字和监听连接的基本步骤:


  首先通过调用listenUsingRfcommWithServiceRecord(String, UUID)方法来获取BluetoothServerSocket对象,参数String代表了该服务的名称,UUID代表了和客户端连接的一个标识(128位格式的字符串ID,相当于PIN码),UUID必须双方匹配才可以建立连接。


  其次调用accept()方法来监听可能到来的连接请求,当监听到以后,返回一个连接上的蓝牙套接字BluetoothSocket。


  最后,在监听到一个连接以后,需要调用close()方法来关闭监听程序。(一般蓝牙设备之间是点对点的传输)


  注意:accept()方法不应该放在主Acitvity里面,因为它是一种阻塞调用(在没有监听到连接请求之前程序就一直停在那里)。解决方法是新建一个线程来管理。例如:




1 private class AcceptThread extends Thread { 2 private final BluetoothServerSocket mmServerSocket; 3 public AcceptThread() { 4 // Use a temporary object that is later assigned to mmServerSocket, 5 // because mmServerSocket is final 6 BluetoothServerSocket tmp = null; 7 try { 8 // MY_UUID is the app's UUID string, also used by theclient code 9 tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);10 } catch (IOException e) { }11 mmServerSocket = tmp;12 }13 14 public void run() {15 BluetoothSocket socket = null;16 // Keep listening until exception occurs or a socket is returned17 while (true) {18 try {19 socket = mmServerSocket.accept();20 } catch (IOException e) {21 break;22 }23 // If a connection was accepted24 if (socket != null) {25 // Do work to manage the connection (in a separate thread)26 manageConnectedSocket(socket);27 mmServerSocket.close();28 break;29 }30 }31 }32 33 /** Will cancel the listening socket, and cause the thread to finish */34 public void cancel() {35 try {36 mmServerSocket.close();37 } catch (IOException e) { }38 }39 }



8. 客户端的连接:


  为了初始化一个与远端设备的连接,需要先获取代表该设备的一个BluetoothDevice对象。通过BluetoothDevice对象来获取BluetoothSocket并初始化连接,具体步骤:


  使用BluetoothDevice对象里的方法createRfcommSocketToServiceRecord(UUID)来获取BluetoothSocket。UUID就是匹配码。然后,调用connect()方法来。如果远端设备接收了该连接,他们将在通信过程中共享RFFCOMM信道,并且connect()方法返回。例如:




1 private class ConnectThread extends Thread { 2 private final BluetoothSocket mmSocket; 3 private final BluetoothDevice mmDevice; 4 public ConnectThread(BluetoothDevice device) { 5 // Use a temporary object that is later assigned to mmSocket, 6 // because mmSocket is final 7 BluetoothSocket tmp = null; 8 mmDevice = device; 9 // Get a BluetoothSocket to connect with the given BluetoothDevice10 try {11 // MY_UUID is the app's UUID string, also used by the server code12 tmp = device.createRfcommSocketToServiceRecord(MY_UUID);13 } catch (IOException e) { }14 mmSocket = tmp;15 }16 17 18 public void run() {19 // Cancel discovery because it will slow down the connection20 mAdapter.cancelDiscovery();21 try {22 // Connect the device through the socket. This will block23 // until it succeeds or throws an exception24 mmSocket.connect();25 } catch (IOException connectException) {26 // Unable to connect; close the socket and get out27 try {28 mmSocket.close();29 } catch (IOException closeException) { }30 return;31 }32 // Do work to manage the connection (in a separate thread)33 manageConnectedSocket(mmSocket);34 }35 }
  注意:conncet()方法也是阻塞调用,一般建立一个独立的线程中来调用该方法。在设备discover过程中不应该发起连接connect(),这样会明显减慢速度以至于连接失败。且数据传输完成只有调用close()方法来关闭连接,这样可以节省系统内部资源。





9. 管理连接(主要涉及数据的传输):


  当设备连接上以后,每个设备都拥有各自的BluetoothSocket。现在你就可以实现设备之间数据的共享了。


  1> 首先通过调用getInputStream()和getOutputStream()方法来获取输入输出流。然后通过调用read(byte[]) 和write(byte[]).方法来读取或者写数据。


  2> 实现细节:以为读取和写操作都是阻塞调用,需要建立一个专用现成来管理。


  3>




1 private class ConnectedThread extends Thread { 2 private final BluetoothSocket mmSocket; 3 private final InputStream mmInStream; 4 private final OutputStream mmOutStream; 5 6 public ConnectedThread(BluetoothSocket socket) { 7 mmSocket = socket; 8 InputStream tmpIn = null; 9 OutputStream tmpOut = null;10 // Get the input and output streams, using temp objects because11 // member streams are final12 try {13 tmpIn = socket.getInputStream();14 tmpOut = socket.getOutputStream();15 } catch (IOException e) { }16 mmInStream = tmpIn;17 mmOutStream = tmpOut;18 }19 20 public void run() {21 byte[] buffer = new byte[1024]; // buffer store for the stream22 int bytes; // bytes returned from read()23 // Keep listening to the InputStream until an exception occurs24 while (true) {25 try {26 // Read from the InputStream27 bytes = mmInStream.read(buffer);28 // Send the obtained bytes to the UI Activity29 mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();30 } catch (IOException e) {31 break;32 }33 }34 }35 36 /* Call this from the main Activity to send data to the remote device */37 public void write(byte[] bytes) {38 try {39 mmOutStream.write(bytes);40 } catch (IOException e) { }41 }42 43 /* Call this from the main Activity to shutdown the connection */44 public void cancel() {45 try {46 mmSocket.close();47 } catch (IOException e) { }48 }49 }



猜你喜欢

转载自201206260201.iteye.com/blog/1688841