Android 蓝牙通信

Android 蓝牙传文件比较常见,但是官方也给出了基于蓝牙通讯做了个聊天室的sample,BluetoothChat。有兴趣的可以下载看下,很有意思。通讯那块用了特殊的BluetoothSocket。思路跟一般socket通讯一样。必须有服务端和客户端。sample有三个类:BluetoothChat,BluetoothChatService,DeviceListActivity。

BluetoothChat是主界面,可以看到聊天的内容,BluetoothChatService是功能类,实现了主要功能,但本身不是一个service,通过BluetoothChat的handle进行UI交互,DeviceListActivity是查找蓝牙设备的功能类

BluettohtChatService的实现逻辑是启动后就是服务端的在等待客户端来建立连接产生socket,当用户选了某个设备建立连接,那个设备就是客户端了,会把服务端的线程断掉。然后就利用BluetoothSocket通讯。用了状态模式来写,很有参考价值。不过很奇怪是一直有两个线程来等待设备接入,叫安全线程,不安全线程。功能一模一样都。

服务器端的实现

通过调用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法来获取BluetoothServerSocket(UUID用于客户端与服务器端之间的配对)

调用BluetoothServerSocket的accept()方法监听连接请求,如果收到请求,则返回一个BluetoothSocket实例(此方法为block方法,应置于新线程中)

如果不想在accept其他的连接,则调用BluetoothServerSocket的close()方法释放资源(调用该方法后,之前获得的BluetoothSocket实例并没有close。但由于RFCOMM一个时刻只允许在一条channel中有一个连接,则一般在accept一个连接后,便close掉BluetoothServerSocket

复制代码
private  class AcceptThread  extends Thread {
     private  final BluetoothServerSocket mmServerSocket;

     public AcceptThread() {
         //  Use a temporary object that is later assigned to mmServerSocket,
        
//  because mmServerSocket is final
        BluetoothServerSocket tmp =  null;
         try {
             //  MY_UUID is the app's UUID string, also used by the client code
            tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
        }  catch (IOException e) { }
        mmServerSocket = tmp;
    }

     public  void run() {
        BluetoothSocket socket =  null;
         //  Keep listening until exception occurs or a socket is returned
         while ( true) {
             try {
                socket = mmServerSocket.accept();
            }  catch (IOException e) {
                 break;
            }
             //  If a connection was accepted
             if (socket !=  null) {
                 //  Do work to manage the connection (in a separate thread)
                manageConnectedSocket(socket);
                mmServerSocket.close();
                 break;
            }
        }
    }

     /**  Will cancel the listening socket, and cause the thread to finish  */
     public  void cancel() {
         try {
            mmServerSocket.close();
        }  catch (IOException e) { }
    }
}
复制代码

 

客户端的实现

通过搜索得到服务器端的BluetoothService

调用BluetoothService的listenUsingRfcommWithServiceRecord(String, UUID)方法获取BluetoothSocket(该UUID应该同于服务器端的UUID)

调用BluetoothSocket的connect()方法(该方法为block方法),如果UUID同服务器端的UUID匹配,并且连接被服务器端accept,则connect()方法返回

注意:在调用connect()方法之前,应当确定当前没有搜索设备,否则连接会变得非常慢并且容易失败

复制代码
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
        mBluetoothAdapter.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) { }
    }
}
复制代码

 

连接管理(数据通信)

分别通过BluetoothSocket的getInputStream()和getOutputStream()方法获取InputStream和OutputStream

使用read(bytes[])和write(bytes[])方法分别进行读写操作

注意:read(bytes[])方法会一直block,知道从流中读取到信息,而write(bytes[])方法并不是经常的block(比如在另一设备没有及时read或者中间缓冲区已满的情况下,write方法会block)

复制代码
private  class ConnectedThread  extends Thread {
     private  final BluetoothSocket mmSocket;
     private  final InputStream mmInStream;
     private  final OutputStream mmOutStream;

     public ConnectedThread(BluetoothSocket socket) {
        mmSocket = socket;
        InputStream tmpIn =  null;
        OutputStream tmpOut =  null;

         //  Get the input and output streams, using temp objects because
        
//  member streams are final
         try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        }  catch (IOException e) { }

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
    }

     public  void run() {
         byte[] buffer =  new  byte[1024];   //  buffer store for the stream
         int bytes;  //  bytes returned from read()

        
//  Keep listening to the InputStream until an exception occurs
         while ( true) {
             try {
                 //  Read from the InputStream
                bytes = mmInStream.read(buffer);
                 //  Send the obtained bytes to the UI Activity
                mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                        .sendToTarget();
            }  catch (IOException e) {
                 break;
            }
        }
    }

     /*  Call this from the main Activity to send data to the remote device  */
     public  void write( byte[] bytes) {
         try {
            mmOutStream.write(bytes);
        }  catch (IOException e) { }
    }

     /*  Call this from the main Activity to shutdown the connection  */
     public  void cancel() {
         try {
            mmSocket.close();
        }  catch (IOException e) { }
    }
}


你可能感兴趣的:(android,聊天,蓝牙,通讯)