蓝牙通信

蓝牙通信的大概步骤如下:

1,首先开启蓝牙

2,搜索可用设备

3,创建蓝牙socket,获取输入输出流

4,读取和写入数据

5,断开连接关闭蓝牙

首先要知道几个类,BluetoothAdapter,BluetoothGatt,BluetoothDevice,BluetoothCattService,BluetoothCattCharacteristic。

第一个是蓝牙设配器,对蓝牙的操作都需要用到它,很重要,BluetoothGatt作为中央来使用和处理数据,使用时有一个回调方法BluetoothGattCallback返回中央的状态和周边提供的数据,BluetoothCattService作为周边来提供数据;BluetoothGattServerCallback返回周边的状态。BluetoothDevice是蓝牙设备,BluetoothCattCharacteristic是蓝牙设备的特征。

看着有点乱,我们来打个比喻:BluetoothDevice为学校,BluetoothGatt为学校到达某一个班级的通道,BluetoothCattService为学校的某一个班级,BluetoothCattCharacteristic为班级中的某一个学生。那么蓝牙连接通信的过程就是这样,BluetoothAdapter先找到学校(就是连接目的设备),再通过通道找到目标班级,最后从班级中找到目标学生,这个学生就是我们设备之间通信的中介,很重要,学校有唯一的MAC地址,班级有唯一的serviceUUID,学生有唯一的charactersticUUID(相当于学号),所以就是在一所学校找一个学生的问题,好了,应该了解了吧。

蓝牙通信原理介绍: 

蓝牙通信和socket通信原理基本上是一致的,下面我给大家上一张图(图为Socket通信图)。

蓝牙客户端Socket的与Sokcet流程是一样的,只不过参数不同而已。如下: 

1、创建客户端蓝牙Sokcet 

2、创建连接 

3、读写数据 

4、关闭

服务端socket: 

1、创建服务端蓝牙Socket 

2、绑定端口号(蓝牙忽略) 

3、创建监听listen(蓝牙忽略, 蓝牙没有此监听,而是通过whlie(true)死循环来一直监听的) 

4、通过accept(),如果有客户端连接,会创建一个新的Socket,体现出并发性,可以同时与多个socket通讯) 

5、读写数据 

6、关闭

下面看客户端代码:

/** 

*Title: ConnectThread

*Description: 客户端逻辑: 客户端的线程,处理客户端socket

*Company: ihaveu

@authorMaWei * @date2017/12/26 */

public classConnectThreadextendsThread{ 

 private static final UUID MY_UUID = UUID.fromString(Constant.CONNECTTION_UUID);

    /** 客户端socket*/    

private final BluetoothSocket mmSoket;

    /** 要连接的设备*/    

private final BluetoothDevice mmDevice;

    private BluetoothAdapter mBluetoothAdapter;

    /** 主线程通信的Handler*/   

 private final Handler mHandler;

    /** 发送和接收数据的处理类*/   

 private ConnectedThread mConnectedThread;

    public ConnectThread(BluetoothDevice device, BluetoothAdapter bluetoothAdapter, Handler mUIhandler) {

        mmDevice = device;

        mBluetoothAdapter = bluetoothAdapter;

        mHandler = mUIhandler;

        BluetoothSocket tmp = null;

        try {

            // 创建客户端Socket

            tmp = device.createRfcommSocketToServiceRecord(MY_UUID);

        } catch (IOException e) {

            e.printStackTrace();

        }

        mmSoket = tmp;

    }

    @Override    public void run() {

        super.run();

        // 关闭正在发现设备.(如果此时又在查找设备,又在发送数据,会有冲突,影响传输效率)

        mBluetoothAdapter.cancelDiscovery();

        try {

            // 连接服务器

            mmSoket.connect();

        } catch (IOException e) {

            // 连接异常就关闭

            try {

                mmSoket.close();

            } catch (IOException e1) {

            }

            return;

        }

        manageConnectedSocket(mmSoket);

    }

    private void manageConnectedSocket(BluetoothSocket mmSoket) {

        // 通知主线程连接上了服务端socket,更新UI

        mHandler.sendEmptyMessage(Constant.MSG_CONNECTED_TO_SERVER);

        // 新建一个线程进行通讯,不然会发现线程堵塞

        mConnectedThread = new ConnectedThread(mmSoket,mHandler);

        mConnectedThread.start();

    }

    /**

    * 关闭当前客户端

    */    public void cancle() {

        try {

            mmSoket.close();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    /**    * 发送数据    * @paramdata    */

    public void sendData(byte[] data) {

        if(mConnectedThread != null) {

            mConnectedThread.write(data);

        }

    }

}

服务端代码:

/** *

Title: AccepThread

*

Description: 服务端Socket通过accept()一直监听客户端连接的线程

*

Company: ihaveu

* * @authorMaWei * @date2017/12/26 */

public classAccepThreadextendsThread{

 /** 连接的名称*/ 

 private static final String NAME = "BluetoothClass";

    /** UUID*/    

private static final UUID MY_UUID = UUID.fromString(Constant.CONNECTTION_UUID);

    /** 服务端蓝牙Sokcet*/    

private final BluetoothServerSocket mmServerSocket;

    private final BluetoothAdapter mBluetoothAdapter;

    /** 线程中通信的更新UI的Handler*/    

private final Handler mHandler;

    /** 监听到有客户端连接,新建一个线程单独处理,不然在此线程中会堵塞*/   

 private ConnectedThread mConnectedThread;

    public AccepThread(BluetoothAdapter adapter, Handler handler) throws IOException {

        mBluetoothAdapter = adapter;

        this.mHandler = handler;

        // 获取服务端蓝牙socket       

 mmServerSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);

    }

    @Override    public void run() {

        super.run();

        // 连接的客户端soacket

        BluetoothSocket socket = null;

        // 服务端是不退出的,要一直监听连接进来的客户端,所以是死循环

        while (true){

            // 通知主线程更新UI,客户端开始监听

            mHandler.sendEmptyMessage(Constant.MSG_START_LISTENING);

            try {

                // 获取连接的客户端socket

                socket =  mmServerSocket.accept();

            } catch (IOException e) {

                // 通知主线程更新UI, 获取异常

                mHandler.sendEmptyMessage(Constant.MSG_ERROR);

                e.printStackTrace();

                // 服务端退出一直监听线程

                break;

            }

            if(socket != null) {

                // 管理连接的客户端socket

                manageConnectSocket(socket);

                // 这里应该是手动断开,案例应该是只保证连接一个客户端,所以连接完以后,关闭了服务端socket

                try {

//                    mmServerSocket.close();

//                    mHandler.sendEmptyMessage(Constant.MSG_FINISH_LISTENING);

//                } catch (IOException e) {

//                    e.printStackTrace();//                }            }

        }

    }

    /**    * 管理连接的客户端socket    

 * @paramsocket    */    

private void manageConnectSocket(BluetoothSocket socket) {

        // 只支持同时处理一个连接

        // mConnectedThread不为空,踢掉之前的客户端

        if(mConnectedThread != null) {

            mConnectedThread.cancle();

        }

        // 主线程更新UI,连接到了一个客户端

        mHandler.sendEmptyMessage(Constant.MSG_GOT_A_CLINET);

        // 新建一个线程,处理客户端发来的数据

        mConnectedThread = new ConnectedThread(socket, mHandler);

        mConnectedThread.start();

    }

    /**

    * 断开服务端,结束监听

    */    public void cancle() {

        try {

            mmServerSocket.close();

            mHandler.sendEmptyMessage(Constant.MSG_FINISH_LISTENING);

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    /**    * 发送数据

    * @paramdata    */    

 public void sendData(byte[] data){

        if(mConnectedThread != null) {

            mConnectedThread.write(data);

        }

    }

}

下面看一个共同通讯处理类:

/** *

Title: ConnectedThread

*Description: 客户端和服务端 处理 发送数据 和获取数据

*/

publicclassConnectedThreadextendsThread{

/** 当前连接的客户端BluetoothSocket*/

privatefinalBluetoothSocket mmSokcet;

/** 读取数据流*/

privatefinalInputStream mmInputStream;

/** 发送数据流*/

privatefinalOutputStream mmOutputStream;

/** 与主线程通信Handler*/

privateHandler mHandler;

privateString TAG ="ConnectedThread";

publicConnectedThread(BluetoothSocket socket,Handler handler) {

 mmSokcet = socket; mHandler = handler;

 InputStream tmpIn =null;

 OutputStream tmpOut =null;

try{ 

         tmpIn = socket.getInputStream();

         tmpOut = socket.getOutputStream(); 

 }catch(IOException e) {

 e.printStackTrace();

 }

 mmInputStream = tmpIn; 

 mmOutputStream = tmpOut;

 }

@Overridepublicvoidrun() {

super.run();

        byte[] buffer =newbyte[1024];

        while(true) {

        try{

// 读取数据

                intbytes = mmInputStream.read(buffer);

           if(bytes >0) {

         String data =newString(buffer,0,bytes,"utf-8");

        // 把数据发送到主线程, 此处还可以用广播

        Message message = mHandler.obtainMessage(Constant.MSG_GOT_DATA,data); 

         mHandler.sendMessage(message); 

}

         Log.d(TAG,"messge size :"+ bytes);

                }catch(IOException e)

                 { e.printStackTrace();

             } 

         } 

 }

// 踢掉当前客户端

publicvoidcancle() {

                try{ 

                    mmSokcet.close();

              }catch(IOException e) { 

             e.printStackTrace(); 

         } 

 }

/** * 服务端发送数据 * 

@paramdata */

publicvoidwrite(byte[] data) {

                    try{ 

                                 mmOutputStream.write(data);

                     }catch(IOException e) { 

                     e.printStackTrace(); 

                 } 

           }

}

你可能感兴趣的:(蓝牙通信)