Bluetooth是目前使用最广泛的无线通讯协议,近距离无线通讯的标准。传说瑞典有个国王特别爱吃蓝莓导致自己的牙齿天天都是蓝色的,在他执政期间这位国王非常善于交际,能说会到,和邻国的搞得关系非常好,这个Bluetooth的发明者觉得蓝牙它的作用就是在近距离沟通周围的设备,跟这个国王很类似,于是起名叫蓝牙。

Android 提供默认的蓝牙协议栈是 BlueDroid,分为两层:蓝牙嵌入式系统(BTE)和蓝牙应用层(BTA),BTE 层主要实现蓝牙的核心功能,BTA 层则主要负责和 Anroid 框架通信
Android 4.2 之前,Google 一直应用的是 Linux 官方蓝牙协议栈,即知名老牌开源
项目 BlueZ。BlueZ 实际上是由高通公司在 2001 年 5 月基于 GPL 协议 release 的一个开源项目,该项目仅 release 一个月后就被 Linux 之父 Linux Torvalds 纳入了 Linux 内核,并做为 Linux 2.4.6 内核的官方蓝牙协议栈。随着 Android 设备的流行,BlueZ 也得到了极大的完善和扩展。例如 Android 4.1 中 BlueZ 的版本升级为 4.93,它支持蓝牙核心规范4.0,并实现了绝大部分的 Profiles。但是从 Android 4.2 即 Jelly Bean 开始,Google 便在 Android 源码中推出了它和博通公司一起开发的 BlueDroid 以替代 BlueZ。虽然因为时间及成熟度的原因,大部分手机厂商在 Android 4.2 中仍继续应用 BlueZ。但是 BlueZ 的创始者,高通公司也将在基于其芯片的 Android 参考设计中去除 BlueZ,并仅支持 BlueDroid。BlueZ 的未来如何笔者姑且不论。不过,能让高通改弦易辙,BlueDroid 自有其合理之处。相比 BlueZ,BlueDroid 最值得称道的地方就是其框架结构变得更为简洁和清晰。另外,借助 HAL(Hardware Abstraction Layer,硬件抽象层),BlueDroid 终于不再和 dbus 有任何瓜葛。(引用)


蓝牙设备连接的过程如下所示:

1、开启蓝牙(开启权限) 

2、查找周围设备 

3、获取设备的name,address 

4、创建BluetoothSocket 

 BluetoothSocket tmp = null; 

 // Get a BluetoothSocket for a connection with the 

 // given BluetoothDevice 

 try { 

 tmp = device.createRfcommSocketToServiceRecord(MY_UUID); 

 } catch (IOException e) { 

 Log.e(TAG, "create() failed", e); 

 }


5、调用connect()链接


主要API
1:BuletoothAdapter
这个类的对象代表了本地的蓝牙适配器,相当于蓝牙工作流程图中的手机里的蓝牙适配器,也就是说比如这个应用程序是运行在手机上,那么手机上的蓝牙适配器就是本地蓝牙适配器。

2:BuletoothDevice
这个类的对象代表了远程的蓝牙设备,相当于蓝牙工作流程图中的计算机里的蓝牙适配器,也就是说比如这个应用程序是运行在手机上,那么BuletoothDevice代表了你要连接的远程的那个设备上面的蓝牙适配器。


/** 

 * 

 * 蓝牙连接线程 

 * 


 * 

 * @author lsw 

 * 

 */ 

 private class ConnectThread extends Thread { 

 String macAddress = ""; 


 public ConnectThread(String mac) { 

 macAddress = mac; 

 } 


 public void run() { 

 connecting = true; 

 connected = false; 

 if(mBluetoothAdapter == null){ 

 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 

 } 

 mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress); 

 mBluetoothAdapter.cancelDiscovery(); 

 //initSocket(); 

 try { 

 socket = mBluetoothDevice.createRfcommSocketToServiceRecord(uuid); 


 } catch (IOException e) { 

 // TODO Auto-generated catch block 

 //e.printStackTrace(); 

 Log.e(TAG, "Socket", e); 

 } 

 //adapter.cancelDiscovery(); 

 while (!connected && connetTime <= 10) { 

 connectDevice(); 

 } 

 // 重置ConnectThread 

 //synchronized (BluetoothService.this) { 

 //ConnectThread = null; 

 //} 

 } 


 public void cancel() { 

 try { 

 socket.close(); 

 socket = null; 

 } catch (Exception e) { 

 e.printStackTrace(); 

 } finally { 

 connecting = false; 

 } 

 } 

 }



接下来是调用的连接设备方法connectDevice():

  
复制代码

protected void connectDevice() { 

 try { 

 // 连接建立之前的先配对 

 if (mBluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE) { 

 Method creMethod = BluetoothDevice.class 

 .getMethod("createBond"); 

 Log.e("TAG", "开始配对"); 

 creMethod.invoke(mBluetoothDevice); 

 } else { 

 } 

 } catch (Exception e) { 

 // TODO: handle exception 

 //DisplayMessage("无法配对!"); 

 e.printStackTrace(); 

 } 

 mBluetoothAdapter.cancelDiscovery(); 

 try { 

 socket.connect(); 

 //DisplayMessage("连接成功!"); 

 //connetTime++; 

 connected = true; 

 } catch (IOException e) { 

 // TODO: handle exception 

 //DisplayMessage("连接失败!"); 

 connetTime++; 

 connected = false; 

 try { 

 socket.close(); 

 socket = null; 

 } catch (IOException e2) { 

 // TODO: handle exception 

 Log.e(TAG, "Cannot close connection when connection failed"); 

 } 

 } finally { 

 connecting = false; 

 } 

 }




利用反射通过端口获得BluetoothSocket,然后执行connect()方法。

  
复制代码

/** 

 * 

 * 蓝牙连接线程 

 * 


 * 

 * @author lsw 

 * 

 */ 

 private class ConnectThread extends Thread { 

 String macAddress = ""; 


 public ConnectThread(String mac) { 

 macAddress = mac; 

 } 


 public void run() { 

 connecting = true; 

 connected = false; 

 if(mBluetoothAdapter == null){ 

 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 

 } 

 mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(macAddress); 

 mBluetoothAdapter.cancelDiscovery(); 

 initSocket(); 

 //adapter.cancelDiscovery(); 

 while (!connected && connetTime <= 10) { 

 try { 

 socket.connect(); 

 connected = true; 

 } catch (IOException e1) { 

 connetTime++; 

 connected = false; 

 // 关闭 socket 

 try { 

 socket.close(); 

 socket = null; 

 } catch (IOException e2) { 

 //TODO: handle exception 

 Log.e(TAG, "Socket", e2); 

 } 

 } finally { 

 connecting = false; 

 } 

 //connectDevice(); 

 } 

 // 重置ConnectThread 

 //synchronized (BluetoothService.this) { 

 //ConnectThread = null; 

 //} 

 } 


 public void cancel() { 

 try { 

 socket.close(); 

 socket = null; 

 } catch (Exception e) { 

 e.printStackTrace(); 

 } finally { 

 connecting = false; 

 } 

 } 

 }



接下来是初始化并得到BluetoothSocket的方法

  
复制代码

/** 

 * 取得BluetoothSocket 

 */ 

 private void initSocket() { 

 BluetoothSocket temp = null; 

 try { 

 Method m = mBluetoothDevice.getClass().getMethod( 

 "createRfcommSocket", new Class[] { int.class }); 

 temp = (BluetoothSocket) m.invoke(mBluetoothDevice, 1);//这里端口为1 

 } catch (SecurityException e) { 

 e.printStackTrace(); 

 } catch (NoSuchMethodException e) { 

 e.printStackTrace(); 

 } catch (IllegalArgumentException e) { 

 e.printStackTrace(); 

 } catch (IllegalAccessException e) { 

 e.printStackTrace(); 

 } catch (InvocationTargetException e) { 

 e.printStackTrace(); 

 } 

 socket = temp; 

 }



要点:1.蓝牙配对和连接是两回事,不可混为一谈。

   2.蓝牙串口连接可通过端口 (1-30)和UUID两种方法进行操作。

   3.通过UUID进行蓝牙连接最好先进行配对操作。