萄京娱乐场官网网站(中国)有限公司

欢迎来到佳祺电子-萄京娱乐场官网网站官网

询价热线

186-6493-4936
萄京娱乐场官网网站:进行蓝牙连接的两种方式

萄京娱乐场官网网站认为为了在两台设备间创建一个连接,必须实现服务器端和客户端的机制,因为一个设备必须打开一个Server Socket,而另一个必须发起连接(使用服务器端设备的MAC地址发起连接)。当服务器端和客户端在同一个RFCOMM信道上都有一个BluetoothSocket时,则两端就建立了连接。此刻,每个设备都能获得一个输入输出流,进行数据传输。


蓝牙耳机认为服务器端和客户端获得BluetoothSocket的方法是不同的,服务器端是在客户端的连接被接受时才产生一个BluetoothSocket,客户端是在打开一个到服务器端的RFCOMM信道时获得BluetoothSocket的。
蓝牙连接的一种实现技术是,每一个设备都自动准备作为一个服务器,所以每个设备都有一个Server Socket并监听连接。然后每个设备都能作为客户端建立一个到另一个设备的连接。


另外一种替代方法是,一个设备按需打开一个Server Socket,另外一个设备仅作为客户端建立与这个设备的连接。

1.作为服务器连接
如果要连接两个设备,其中一个必须充当服务器,它拥有BluetoothServerSocket。服务器Socket的作用是侦听进来的连接,且在一个连接被接受时返回一个BluetoothSocket对象。

从BluetoothServerSocket获取到BluetoothSocket对象之后,BluetoothServerSocket就可以(也应该)丢弃了,除非还要用它接收更多的连接。


下面是建立服务器Socket和接受一个连接的基本步骤:


步骤1 通过调用listenUsingRfcommWithServiceRecord(String, UUID)方法得到一个BluetoothServerSocket对象。字符串参数为服务的标识名称,名字是任意的,可以简单地是应用程序的名称。当客户端试图连接本设备时,它将携带一个UUID用来唯一标识它要连接的服务,UUID必须匹配,连接才会被接受。


步骤2 通过调用accept()来侦听连接请求。这是一个阻塞线程,直到接受一个连接或者产生异常才会返回。当客户端携带的UUID与侦听它Socket注册的UUID匹配,连接请求才会被接受。如果成功,accept()将返回一个BluetoothSocket对象。


步骤3 除非需要再接受另外的连接,否则的话调用close()。close()释放Server Socket及其资源,但不会关闭accept()返回的BluetoothSocket对象。与TCP/IP不同,RFCOMM同一时刻一个信道只允许一个客户端连接,因此大多是情况下意味着在BluetoothServerSocket接受一个连接请求后应该马上调用close()。


accept()调用不应该在主Activity UI线程中进行,因为它是个阻塞线程,会妨碍应用中其他的交互。通常在一个新线程中做BluetoothServerSocket或BluetoothSocket的所有工作来避免线程阻塞。如果需要放弃阻塞线程,可以调用close()方法。


下面萄京娱乐场官网网站整理的一个服务器组件接受连接的线程示例。


	
  1. //定义接受线程
  2. private class AcceptThread extends Thread {
  3. //创建BluetoothServerSocket类
  4. private final BluetoothServerSocket mmServerSocket;
  5. public AcceptThread() {
  6. BluetoothServerSocket tmp = null;
  7. try {
  8. //MY_UUID是应用的UUID标识
  9. tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
  10. } catch(IOException e) {}
  11. mmServerSocket = tmp;
  12. }
  13. //线程启动时候运行
  14. public void run() {
  15. BluetoothSocket socket = null;
  16. //保持侦听
  17. while(true) {
  18. try {
  19. //接受
  20. socket = mmServerSocket.accept();
  21. } catch(IOException e) {
  22. break;
  23. }
  24. //连接被接受
  25. if(socket!=null) {
  26. //管理连接
  27. manageConnectedSocket(socket);
  28. //关闭连接
  29. mmServerSocket.close();
  30. break;
  31. }
  32. }
  33. }
  34. //关闭连接
  35. public void cancel() {
  36. try
  37. {
  38. //关闭BluetoothServerSocket
  39. mmServerSocket.close();
  40. }
  41. catch(IOException e) {}
  42. }
  43. }

本例中,只接受一个进来的连接,一旦连接被接受并获取BluetoothSocket,应用就发送获取到的BluetoothSocket给一个单独的线程,然后关闭BluetoothServerSocket并跳出循环。
---------------------
注意 accept()返回BluetoothSocket后,Socket就建立了连接,所以在客户端就不应该再调用connect()。
---------------------

 

2.作为客户端连接

为了实现与远程服务器设备的连接,必须首先获得一个代表远程设备BluetoothDevice的对象。然后使用BluetoothDevice对象来获取一个BluetoothSocket以实现连接。


基本步骤如下:
步骤1 使用BluetoothDevice调用方法createRfcommSocketToServiceRecord(UUID)获取一个BluetoothSocket对象。


步骤2 调用connect()建立连接。当调用这个方法的时候,系统会在远程设备上完成一个SDP查找来匹配UUID。如果查找成功并且远程设备接受连接,就共享RFCOMM信道,connect()会返回。这个方法也是一个阻塞的调用。如果连接失败或者超时(12秒)都会抛出异常。


---------------------
注意 要确保在调用connect()时没有同时做设备搜索,如果在搜索设备,该连接尝试会显著变慢,容易导致连接失败。

---------------------


下面是一个发起Bluetooth连接的线程示例。


	
  1. //定义Bluetooth连接线程
  2. private class ConnectThread extends Thread {
  3. //新建BluetoothSocket类
  4. private final BluetoothSocket mmSocket;
  5. //新建BluetoothDevice对象
  6. private final BluetoothDevice mmDevice;
  7. public ConnectThread(BluetoothDevice device) {
  8. BluetoothSocket tmp = null;
  9. //赋值给设备
  10. mmDevice = device;
  11. try {
  12. //根据UUID创建并返回一个BluetoothSocket
  13. tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
  14. } catch(IOException e) {}
  15. //赋值给BluetoothSocket
  16. mmSocket = tmp;
  17. }
  18. public void run() {
  19. //取消发现设备
  20. mBluetoothAdapter.cancelDiscovery();
  21. try {
  22. //连接到设备
  23. mmSocket.connect();
  24. } catch(IOException connectException) {
  25. //无法连接,关闭Socket
  26. try
  27. {
  28. mmSocket.close();
  29. }
  30. catch (IOException connectException) {}
  31. return;
  32. }
  33. //管理连接
  34. manageConnectedSocket(mmSocket);
  35. }
  36. //取消连接
  37. public void cancel() {
  38. try
  39. {
  40. //关闭BluetoothSocket
  41. mmSocket.close();
  42. }
  43. catch(IOException e) {}
  44. }
  45. }

注意:cancelDiscovery()应用连接操作前被调用。在连接之前,不管搜索有没有进行。该调用都是安全的,不需要确认(当然如果要确认,可以调用isDiscovering()方法)。处理完后别忘了调用close()方法来关闭连接的Socket和释放所有的内部资源。

 

3.管理连接

如果两个设备成功建立了连接,各自会有一个BluetoothSocket,此时可以在设备间共享数据了。使用BluetoothSocket,传输任何数据通常来说都比较容易,通常如下进行:


+分别使用getInputStream()和getOutputStream()获取输入输出流来处理传输。
+调用read(byte[])和write(byte[])来实现数据读写。


当然,萄京娱乐场官网网站提醒要注意一些实现细节。比如,需要用一个专门的线程来实现流的读写,因为方法read(byte[])和write(byte[])都是阻塞调用。read(byte[])会阻塞,直到流中有数据可读。write(byte[])虽然通常不会阻塞,但是如果远程设备调用read(byte[])不够快而导致中间缓冲区满,它也可能阻塞。所以线程中的主循环应该用于读取InputStream。线程中也应该有单独的方法用来完成写OutputStream。
请看下面的示例:


	
  1. //连接管理线程
  2. private class ConnectThread extends Thread {
  3. //新建BluetoothSocket类
  4. private final BluetoothSocket mmSocket;
  5. //新建输入流对象
  6. private final InputStream mmInStream;
  7. //新建输出流对象
  8. private final OutputStream mmOutStream;
  9. public ConnectThread(BluetoothSocket socket) {
  10. //为BluetoothSocket赋初始值
  11. mmSocket = socket;
  12. //输入流赋值为null
  13. InputStream tmpIn = null;
  14. //输出流赋值为null
  15. OutputStream tmpOut = null;
  16. try {
  17. //从BluetoothSocket中获取输入流
  18. tmpIn = socket.getInputStream();
  19. //从BluetoothSocket中获取输出流
  20. tmpOut = socket.getOutputStream();
  21. } catch(IOException e) {}
  22. //为输入流赋值
  23. mmInStream = temIn;
  24. //为输出流赋值
  25. mmOutStream = temOut;
  26. }
  27. public void run() {
  28. //流的缓冲大小
  29. byte[] buffer = new byte[1024];
  30. //用于保存read()所读取的字节数
  31. int bytes;
  32. while(true) {
  33. try
  34. {
  35. //从输入流中读取数据
  36. bytes = mmInStream.read(buffer);
  37. //发送数据到界面
  38. mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();
  39. }
  40. catch ()
  41. {
  42. break;
  43. }
  44. }
  45. }
  46. //发送数据到远程设备
  47. public void write(byte[] bytes) {
  48. try
  49. {
  50. //写数据到输出流中
  51. mmOutStream.write(bytes);
  52. }
  53. catch(IOException e) {}
  54. }
  55. //取消
  56. public void cancel() {
  57. try
  58. {
  59. //关闭B连接
  60. mmSocket.close();
  61. }
  62. catch(IOException e) {}
  63. }
  64. }

构造函数中得到需要的流,一旦实行,线程会等待从InputStream来的数据,当read(byte[])返回从流中读到的字节后,数据通过父类的成员Handler被送到主Activity,然后继续等待读取流中的数据。向外发送数据只需简单地调用线程的write()方法。线程的cancel()方法是很重要的,以便连接可以在任何时候通过关闭BluetoothSocket来终止。它总在处理完Bluetooth连接后被调用。

  • 上一篇:蓝牙耳机代工多年,萄京娱乐场官网网站如何拓展外贸业务
  • 下一篇:萄京娱乐场官网网站:Android蓝牙连接的一些心得
  • 佳祺电子-TWS萄京娱乐场官网网站
    欢迎全国各渠道商来电询价
    全国服务热线:

    186-6493-4936

    萄京娱乐场官网网站|萄京娱乐场官网网站

    XML 地图 | Sitemap 地图