android蓝牙开发——二

 

为了在两台设备上创建一个连接,你必须在软件上实现服务器端和客户端的机制,因为一个设备必须必须打开一个server socket,而另一个必须初始化这个连接(使用服务器端设备的MAC地址进行初始化)。

当服务器端和客户端在同一个RFCOMM信道上都有一个BluetoothSocket时,就可以认为它们之间建立了一个连接。在这个时刻,每个设备能获得一个输出流和一个输入流,也能够开始数据传输。本节介绍如何在两个设备之间初始化一个连接。

服务器端和客户端获得BluetoothSocket的方法是不同的,服务器端是当一个进入的连接被接受时才产生一个BluetoothSocket,客户端是在打开一个到服务器端的RFCOMM信道时获得BluetoothSocket的。

远程设备请求配对

  Figure 3: The Bluetooth pairing dialog.

 

 一种实现技术是,每一个设备都自动作为一个服务器,所以每个设备都有一个server socket并监听连接。然后每个设备都能作为客户端建立一个到另一台设备的连接。另外一种代替方法是,一个设备按需打开一个server socket,另外一个设备仅初始化一个到这个设备的连接。

 

Note: 如果两个设备在建立连接之前并没有配对,那么在建立连接的过程中,Android框架将自动显示一个配对请求的notification或者一个对话框,如Figure 3所示。所以,在尝试连接设备时,你的应用程序无需确保设备之间已经进行了配对。你的RFCOMM连接将会在用户确认配对之后继续进行,或者用户拒绝或者超时之后失败。

作为一个服务器进行连接

当你想要连接两个设备时,其中一个必须保持一个打开的BluetoothServerSocket,作为服务器。服务器socket将监听进入的连接请求,一旦连接被接受,将产生一个BluetoothSocket。

  1. 调用listenUsingRfcommWithServiceRecord(String, UUID)获得一个BluetoothServerSocket

    字符串参数是你的服务的标识名,系统将自动将这个标识名写到设备上一个新的Service Discovery Protocol(SDP)数据库条目中(这个标识名可以简单地作为你的程序的名字,也就是说可以把你的程序的名字作为命名)。UUID也会被包含在这个新的SDP条目中,并作为与客户端设备建立连接的基础。 That is, when the client attempts to connect with this device, it will carry a UUID that uniquely identifies the service with which it wants to connect. These UUIDs must match in order for the connection to be accepted (in the next step).

  2. 调用accept()开始监听连接请求

    这是一个阻塞调用。当一个连接被接受或者发生异常时将返回。一个连接,仅当一个远程设备发出的请求包含UUID匹配正在监听的server socket所注册的UUID时被接受。成功的时候,accept()将返回一个连接的BluetoothSocket。

  3. 除非你要接受另外一个连接,否则调用close,关闭server socket。

    这将释放server socket和它占用的所有资源,但不要用来关闭accept返回的已连接的BluetoothSocket。不像TCP/IP,RFCOMM仅允许一个信道在某一时刻有一个连接的客户端。所以,创建了一个连接的socket之后立即调用close()来关闭BluetoothServerSocket。

accept()方法不应该在主Activity UI线程中执行,因为它是一个阻塞调用,如果在主Activity UI线程中条也能够将会阻止与用户的交互。一般使用BluetoothServerSocket或者BluetoothSocket进行相关工作时都是在一个新的线程中。为了避免调用诸如accept()这样的阻塞调用,针对来自其他线程的BluetoothServerSocket或者BluetoothSocket调用close()将会使阻塞调用立即返回。注意,针对BluetoothServerSocket或者BluetoothSocket调用的方法都是线程安全的,也就是说可以在多个线程中使用。

示例

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

 

 

manageConnectedSocket() 这个方法能初始化用于传输数据的线程。

 

感觉这些英语基本上都能看懂,就不翻译了...

Connecting as a client

In order to initiate a connection with a remote device (a device holding an open server socket), you must first obtain a BluetoothDevice object that represents the remote device. (Getting a BluetoothDevice is covered in the above section about Finding Devices.) You must then use the BluetoothDevice to acquire a BluetoothSocket and initiate the connection.

Here's the basic procedure:

  1. Using the BluetoothDevice, get a BluetoothSocket by calling createRfcommSocketToServiceRecord(UUID).

    This initializes a BluetoothSocket that will connect to the BluetoothDevice. The UUID passed here must match the UUID used by the server device when it opened its BluetoothServerSocket (with listenUsingRfcommWithServiceRecord(String, UUID)). Using the same UUID is simply a matter of hard-coding the UUID string into your application and then referencing it from both the server and client code.

  2. Initiate the connection by calling connect().

    Upon this call, the system will perform an SDP lookup on the remote device in order to match the UUID. If the lookup is successful and the remote device accepts the connection, it will share the RFCOMM channel to use during the connection and connect() will return. This method is a blocking call. If, for any reason, the connection fails or the connect() method times out (after about 12 seconds), then it will throw an exception.

    Because connect() is a blocking call, this connection procedure should always be performed in a thread separate from the main Activity thread.

    Note: You should always ensure that the device is not performing device discovery when you call connect(). If discovery is in progress, then the connection attempt will be significantly slowed and is more likely to fail.

Example

Here is a basic example of a thread that initiates a Bluetooth connection:

private class ConnectThread extends Thread {
    private final BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;

    public ConnectThread(BluetoothDevice device) {
        // Use a temporary object that is later assigned to mmSocket,
        // because mmSocket is final
        BluetoothSocket tmp = null;
        mmDevice = device;

        // Get a BluetoothSocket to connect with the given BluetoothDevice
        try {
            // MY_UUID is the app's UUID string, also used by the server code
            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
        } catch (IOException e) { }
        mmSocket = tmp;
    }

    public void run() {
        // Cancel discovery because it will slow down the connection
        mAdapter.cancelDiscovery();

        try {
            // Connect the device through the socket. This will block
            // until it succeeds or throws an exception
            mmSocket.connect();
        } catch (IOException connectException) {
            // Unable to connect; close the socket and get out
            try {
                mmSocket.close();
            } catch (IOException closeException) { }
            return;
        }

        // Do work to manage the connection (in a separate thread)
        manageConnectedSocket(mmSocket);
    }

    /** Will cancel an in-progress connection, and close the socket */
    public void cancel() {
        try {
            mmSocket.close();
        } catch (IOException e) { }
    }
}

Notice that cancelDiscovery() is called before the connection is made. You should always do this before connecting and it is safe to call without actually checking whether it is running or not (but if you do want to check, call isDiscovering()).

manageConnectedSocket() is a fictional method in the application that will initiate the thread for transferring data, which is discussed in the section about Managing a Connection.

When you're done with your BluetoothSocket, always call close() to clean up. Doing so will immediately close the connected socket and clean up all internal resources.

 
 

当你成功地连接了两台(或多台)设备时,每个设备都有一个已连接的BluetoothSocket。这时你可以在设备之间共享数据,乐趣才刚开始。 使用BluetoothSocket,传输二进制数据的过程是简单的:

  1. 分别通过getInputStream()和getOutputStream()获得管理数据传输的InputStream和OutputStream。
  2. 通过read(byte[])和write(byte[])从流中读取或写入数据。

 首先,你必须使用一个线程专门用于数据的读或写。这是非常重要的,因为read(byte[])和write(byte[])方法都是阻塞调用。read(byte[])将会阻塞到流中有数据可读。write(byte[])一般不会阻塞,但当远程设备的中间缓冲区已满而对方没有及时地调用read(byte[])时将会一直阻塞。所以,你的线程中的主循环将一直用于从InputStream中读取数据。 A separate public method in the thread can be used to initiate writes to the OutputStream.

Example

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

BLE(低功耗蓝牙)是一种通过蓝牙无线技术进行低功耗通信的协议。它是在传统蓝牙(Classic Bluetooth)的基础上发展而来,主要用于物联网、智能家居和健康追踪等领域。 BLE主要特点有以下几个方面: 1. 低功耗:BLE采用了一种优化的通信方式,使设备在通信过程中的功耗大大降低,从而延长了设备的电池寿命,这对于需要长时间运行的设备非常重要。 2. 简化传输:BLE使用了一种称为GATT(通用属性)的协议,将数据分为服务和特征,通过读、写或订阅操作来传输数据,这种简化了传输过程,减少了额外的开销。 3. 快速连接:BLE的连接速度比传统蓝牙更快,可以在几十毫秒内建立连接,这对于移动设备和传感器等需要快速响应的设备非常重要。 4. 多设备连接:BLE支持同时连接多个设备,可以通过同一个移动设备与多个BLE设备进行通信,提高了系统的灵活性和可扩展性。 Android提供了一套完整的BLE开发API,开发者可以使用这些API来实现BLE通信功能。在Android中,开发BLE应用涉及到四个主要组件:BLE设备扫描、设备连接、数据传输和GATT服务管理。 开发者可以使用Android的BluetoothAdapter类来进行设备扫描和连接操作,可以通过BluetoothGatt类来进行GATT服务的操作,包括读、写、订阅等。 总之,BLE作为一种低功耗的蓝牙通信协议,在物联网和智能设备领域应用广泛。在Android平台上进行BLE开发,可以借助Android提供的API,快速实现BLE通信功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值