蓝牙通信的简要设计与开发

Posted 林颖宝贝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝牙通信的简要设计与开发相关的知识,希望对你有一定的参考价值。

蓝牙通信步骤

具体步骤

1,首先开启蓝牙
2、搜索可用设备
3、创建蓝牙socket,获取输入输出流
4、读取和写入数据
5、断开连接关闭蓝牙

过程图及其文字描述


1.执行oncreate方法打开蓝牙,不需要经过用户的同意;
2.通过注册广播接收器获取搜索到的蓝牙设备,在列表上显示搜索到的设备;
3.点击所显示的设备调连接蓝牙的代码请求连接!
4.连接具体解释,连接时和socket聊天的方式近似;
5在此做出假设;假设蓝牙设备A向蓝牙设备B发送一串文字;首先调用相关的蓝牙连接代码建立连接;
6获取输出流通过socket发送数据到另外—个蓝牙设备;需要设置发送时的ID∶定义类似端口类型的;
7.接收端设备B需要获取输入流读取蓝牙设备A发送过来的消息;然后在界面上显示;

蓝牙通信原理

首先要知道几个类
BluetoothAdapter:代表本地蓝牙适配器(蓝牙无线电)。BluetoothAdapter是所有蓝牙交互的入口。使用这个你可以发现其他蓝牙设备,查询已配对的设备列表,使用一个已知的MAC地址来实例化一个BluetoothDevice,以及创建一个BluetoothServerSocket来为监听与其他设备的通信。
BluetoothGatt:BluetoothGatt作为中央来使用和处理数据,使用时有一个回调方法BluetoothGattCallback返回中央的状态和周边提供的数据
BluetoothDevice:代表一个远程蓝牙设备,使用这个来请求一个与远程设备的BluetoothSocket连接,或者查询关于设备名称、地址、类和连接状态等设备信息。
BluetoothCattService:BluetoothCattService作为周边来提供数据
BluetoothCattCharacteristic:BluetoothCattCharacteristic是蓝牙设备的特征
BluetoothGattServerCallback:BluetoothGattServerCallback返回周边的状态

蓝牙客户端socket工作步骤

1、创建客户端蓝牙Sokcet
2、创建连接
3、读写数据
4、关闭

蓝牙服务端socket工作步骤

1、创建服务端蓝牙Socket
2、绑定端口号(蓝牙忽略)
3、创建监听listen(蓝牙忽略, 蓝牙没有此监听,而是通过whlie(true)死循环来一直监听的)
4、通过accept(),如果有客户端连接,会创建一个新的Socket,体现出并发性,可以同时与多个socket通讯)
5、读写数据
6、关闭

android Studio实现

配置权限

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

状态描述文本及配色

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">MyBluetooth</string>
    <string name="send">发送</string>
    <string name="not_connected">你没有链接一个设备</string>
    <string name="bt_not_enabled_leaving">蓝牙不可用,离开聊天室</string>
    <string name="title_connecting">链接中...</string>
    <string name="title_connected_to">连接到:</string>
    <string name="title_not_connected">无链接</string>
    <string name="scanning">蓝牙设备搜索中...</string>
    <string name="select_device">选择一个好友链接</string>
    <string name="none_paired">没有配对好友</string>
    <string name="none_found">附近没有发现好友</string>
    <string name="title_paired_devices">已配对好友</string>
    <string name="title_other_devices">其它可连接好友</string>
    <string name="button_scan">搜索好友</string>
    <string name="connect">我的好友</string>
    <string name="discoverable">设置在线</string>
    <string name="back">退出</string>
    <string name="startVideo">开始聊天</string>
    <string name="stopVideo">结束聊天</string>
</resources>

蓝牙服务

public class ChatService 
    //本应用的主Activity组件名称
    private static final String NAME = "BluetoothChat";
    // UUID:通用唯一识别码,是一个128位长的数字,一般用十六进制表示
    //算法的核心思想是结合机器的网卡、当地时间、一个随机数来生成
    //在创建蓝牙连接
    private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
    private final BluetoothAdapter mAdapter;
    private final Handler mHandler;
    private AcceptThread mAcceptThread;
    private ConnectThread mConnectThread;
    private ConnectedThread mConnectedThread;
    private int mState;
    public static final int STATE_NONE = 0;
    public static final int STATE_LISTEN = 1;
    public static final int STATE_CONNECTING = 2;
    public static final int STATE_CONNECTED = 3;

    //构造方法,接收UI主线程传递的对象
    public ChatService(Context context, Handler handler) 
        //构造方法完成蓝牙对象的创建
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mState = STATE_NONE;
        mHandler = handler;
    

    private synchronized void setState(int state) 
        mState = state;
        mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
    

    public synchronized int getState() 
        return mState;
    

    public synchronized void start() 
        if (mConnectThread != null) 
            mConnectThread.cancel();
            mConnectThread = null;
        
        if (mConnectedThread != null) 
            mConnectedThread.cancel();
            mConnectedThread = null;
        
        if (mAcceptThread == null) 
            mAcceptThread = new AcceptThread();
            mAcceptThread.start();
        
        setState(STATE_LISTEN);
    

    //取消 CONNECTING 和 CONNECTED 状态下的相关线程,然后运行新的 mConnectThread 线程
    public synchronized void connect(BluetoothDevice device) 
        if (mState == STATE_CONNECTING) 
            if (mConnectThread != null) 
                mConnectThread.cancel();
                mConnectThread = null;
            
        
        if (mConnectedThread != null) 
            mConnectedThread.cancel();
            mConnectedThread = null;
        
        mConnectThread = new ConnectThread(device);
        mConnectThread.start();
        setState(STATE_CONNECTING);
    

    /*
        开启一个 ConnectedThread 来管理对应的当前连接。之前先取消任意现存的 mConnectThread 、
        mConnectedThread 、 mAcceptThread 线程,然后开启新 mConnectedThread ,传入当前刚刚接受的
        socket 连接。最后通过 Handler来通知UI连接
     */
    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) 
        if (mConnectThread != null) 
            mConnectThread.cancel();
            mConnectThread = null;
        
        if (mConnectedThread != null) 
            mConnectedThread.cancel();
            mConnectedThread = null;
        
        if (mAcceptThread != null) 
            mAcceptThread.cancel();
            mAcceptThread = null;
        
        mConnectedThread = new ConnectedThread(socket);
        mConnectedThread.start();
        Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);
        setState(STATE_CONNECTED);
    

    // 停止所有相关线程,设当前状态为 NONE
    public synchronized void stop() 
        if (mConnectThread != null) 
            mConnectThread.cancel();
            mConnectThread = null;
        
        if (mConnectedThread != null) 
            mConnectedThread.cancel();
            mConnectedThread = null;
        
        if (mAcceptThread != null) 
            mAcceptThread.cancel();
            mAcceptThread = null;
        
        setState(STATE_NONE);
    

    // 在 STATE_CONNECTED 状态下,调用 mConnectedThread 里的 write 方法,写入 byte
    public void write(byte[] out) 
        ConnectedThread r;
        synchronized (this) 
            if (mState != STATE_CONNECTED)
                return;
            r = mConnectedThread;
        
        r.write(out);
    

    // 连接失败的时候处理,通知 ui ,并设为 STATE_LISTEN 状态
    private void connectionFailed() 
        setState(STATE_LISTEN);
        Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(BluetoothChat.TOAST, "链接不到设备");
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    

    // 当连接失去的时候,设为 STATE_LISTEN 状态并通知 ui
    private void connectionLost() 
        setState(STATE_LISTEN);
        Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(BluetoothChat.TOAST, "设备链接中断");
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    

    // 创建监听线程,准备接受新连接。使用阻塞方式,调用 BluetoothServerSocket.accept()
    private class AcceptThread extends Thread 
        private final BluetoothServerSocket mmServerSocket;

        public AcceptThread() 
            BluetoothServerSocket tmp = null;
            try 
                //使用射频端口(RF comm)监听
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
             catch (IOException e) 
            
            mmServerSocket = tmp;
        

        @Override
        public void run() 
            setName("AcceptThread");
            BluetoothSocket socket = null;
            while (mState != STATE_CONNECTED) 
                try 
                    socket = mmServerSocket.accept();
                 catch (IOException e) 
                    break;
                
                if (socket != null) 
                    synchronized (ChatService.this) 
                        switch (mState) 
                            case STATE_LISTEN:
                            case STATE_CONNECTING:
                                connected(socket, socket.getRemoteDevice());
                                break;
                            case STATE_NONE:
                            case STATE_CONNECTED:
                                try 
                                    socket.close();
                                 catch (IOException e) 
                                    e.printStackTrace();
                                
                                break;
                        
                    
                
            
        

        public void cancel() 
            try 
                mmServerSocket.close();
             catch (IOException e) 
                e.printStackTrace();
            
        
    

    /*
        连接线程,专门用来对外发出连接对方蓝牙的请求和处理流程。
        构造函数里通过 BluetoothDevice.createRfcommSocketToServiceRecord() ,
        从待连接的 device 产生 BluetoothSocket. 然后在 run 方法中 connect ,
        成功后调用 BluetoothChatSevice 的 connected() 方法。定义 cancel() 在关闭线程时能够关闭相关socket 。
     */
    private class ConnectThread extends Thread 
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device) 
            mmDevice = device;
            BluetoothSocket tmp = null;
            try 
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
             catch (IOException e) 
                e.printStackTrace();
            
            mmSocket = tmp;
        

        @Override
        public void run() 
            setName("ConnectThread");
            mAdapter.cancelDiscovery();
            try 
                mmSocket.connect();
             catch (IOException e) 
                connectionFailed();
                try 
                    mmSocket.close();
                 catch (IOException e2) 
                    e.printStackTrace();
                
                ChatService.this.start();
                return;
            
            synchronized (ChatService.this) 
                mConnectThread = null;
            
            connected(mmSocket, mmDevice);
        

        public void cancel() 
            try 
                mmSocket.close();
             catch (IOException e) 
                e.printStackTrace();
            
        
    

    /*
        双方蓝牙连接后一直运行的线程;构造函数中设置输入输出流。
        run()方法中使用阻塞模式的 InputStream.read()循环读取输入流,然后发送到 UI 线程中更新聊天消息。
        本线程也提供了 write() 将聊天消息写入输出流传输至对方,传输成功后回写入 UI 线程。最后使用cancel()关闭连接的 socket
     */
    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;
            try 
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
             catch (IOException e) 
                e.printStackTrace();
            
            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        

        @Override
        public void run() 
            byte[] buffer = new byte[1024];
            int bytes;
            while (true) 
                try 
                    bytes = mmInStream.read(buffer);
                    mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer).sendToTarget();
                 catch (IOException e) 
                    connectionLost();
                    break;
                
            
        

        public void write(byte[] buffer) 
            try 
                mmOutStream.write(buffer);
                mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer).sendToTarget();
             catch (IOException e) 
                eAndroid蓝牙开发——实现蓝牙聊天

固件空中升级(OTA)与固件二次引导的原理和设计

经典蓝牙Android开发(通信)

读书笔记iOS-使用蓝牙

Android 与 Ubuntu 的蓝牙串行通信

无线通信 - 由于Android应用开发蓝牙〜SPP