• 蓝牙通信测试app之蓝牙通信(二)


    蓝牙通信开发流程

    为了让两个设备上的两个应用程序之间建立连接,你必须同时实现服务端和客户端机制。

    • 服务端:使用的是 BluetoothServerSocket 类,并且调用的是 listenUsingRfcommWithServiceRecord(string,UUID) 方法来获得一个BluetoothServerSocket对象。
    • 客户端:使用的是 BluetoothSocket 类,调用的是 createRfcommSocketToServiceRecord(UUID) 方法,这里的 UUID 会和服务端的UUID进行比较,如果匹配就能获得一个BluetoothSocket 对象。
    • 公共端:在连接后,都会进入已连接线程。会在这个线程中进行写入和读取。

    经典蓝牙连接相当于socket连接,是个非常耗时的操作,所以应该放到子线程中去完成。

    服务端的监听线程:

    // 创建监听线程,准备接受新连接。使用阻塞方式,调用BluetoothServerSocket.accept()
    private class AcceptThread extends Thread {
        private final BluetoothServerSocket mmServerSocket;
        public AcceptThread(){
            BluetoothServerSocket tmp = null;
            try{
                //MY_UUID用于唯一标识当前的蓝牙服务,在建立连接时会被客户端使用
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME,MY_UUID);
            }catch (IOException e){}
            mmServerSocket = tmp;
        }
        public void run(){
            BluetoothSocket socket= null;
            while(mState != STATE_CONNECTED){
                try{
                    // 保持监听状态,并阻塞线程,当连接建立时返回。
                    socket = mmServerSocket.accept();
                }catch (IOException e) {
                    break;
                }
                if(socket != null){
                    //在单独的线程中对连接进行管理,本线程结束
                    ConnectedThread mConnectedThread = new ConnectedThread(socket);
                    mConnectedThread.start();
                    try{
                        mmServerSocket.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
        }
        public void cancel(){
            try{
                mmServerSocket.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
    

    客户端的连接线程:

    private class ConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;
        public ConnectThread(BluetoothDevice device){
            Log.e("ChatTag", " -- ConnectThread -- ");
            mmDevice=device;
            BluetoothSocket tmp = null;
            //获取一个 BluetoothSocket 以连接给定的 BluetoothDevice
            try{
                // MY_UUID 是应用程序的 UUID 字符串,也由服务器代码使用
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            }catch (IOException e){
                e.printStackTrace();
            }
            mmSocket = tmp;
        }
    
        public void run(){
            // 取消发现,因为它会减慢连接速度
            mAdapter.cancelDiscovery();
            try{
                // 请求连接,该操作会阻塞线程
                // 直到成功或抛出异常
                mmSocket.connect();
            }catch (IOException e){
                e.printStackTrace();
                // Unable to connect; close the socket and get out
                try{
                    mmSocket.close();
                }catch (IOException e2){}
                //ChatService.this.start();
                return;
            }
            synchronized(ChatService.this){
                mConnectedThread = null;
            }
            // 连接已建立,在单独的线程中对连接进行管理
            ConnectedThread mConnectedThread = new ConnectedThread(socket);
            mConnectedThread.start();
        }
    
        public void cancel(){
            /* try{
                mmSocket.close();
            }catch (IOException e){}*/
        }
    }
    

    公共端的已连接线程:

    // 双方蓝牙连接后一直运行的线程。构造函数中设置输入输出流
    // Run方法中使用阻塞模式的Inputstream.read()循环读取输入流
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private  InputStream mmInStream;
        private  OutputStream mmOutStream;
    
        public ConnectedThread(BluetoothSocket socket){
            Log.e("ChatTag", " -- ConnectedThread -- ");
            mmSocket = socket;
            // 使用临时对象获取输入和输出流
            try{
                mmInStream = mmSocket.getInputStream();
                mmOutStream = mmSocket.getOutputStream();
            }catch (IOException e){}
        }
    
        public void run(){
            byte[]buffer=new byte[1024];
            int bytes;
            //读数据需要不断监听 ,写 不需要
            while (true) {
                try {
                    //读取 InputStream 的数据
                    bytes = mmInStream.read(buffer);
                } catch (IOException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }
    
        public void write(byte[]buffer){
            try{
                mmOutStream.write(buffer);
            }catch (IOException e){
                 e.printStackTrace();
            }
        }
    
        public void cancel(){
            try{
                mmSocket.close();
            }catch (IOException e){}
        }
    }
    

    调用流程

    • 在 主视图 的 onResume () 方法中,调用监听线程,等着被连接。

    • 在蓝牙配对的流程中,在配对后会将配对的蓝牙设备地址 放入 Intent;

    • 在 主视图 的 onActivityResult () 方法中,能从 Intent 中获取蓝牙设备地址

      // 获取 蓝牙适配器
      BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
      // 通过蓝牙设备地址,获取 蓝牙设备
      BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
      
      // 然后调用连接线程,进行连接
      ConnectThread mConnectThread = new ConnectThread(device);
      mConnectThread.start();
      
    • 然后调用连接线程,请求连接服务端

    • 当连接通过后,客户端和服务端就可以进行通信了。

    十万签名内容......
  • 相关阅读:
    【服务器数据恢复】StorNext文件系统数据恢复案例
    【数据库数据恢复】ASM磁盘组掉线,ASM实例不能mount的Oracle数据库数据恢复案例
    【服务器数据恢复】硬盘坏道和不稳定扇区导致服务运行过程中器崩溃的数据恢复案例
    【服务器数据恢复】重装系统导致XFS文件系统分区无法访问的数据恢复
    家中电脑的Vscode配置
    编码 乱码 解析 识别
    重构代码架构使具有良好扩展性
    第二单元总结性博客作业
    C语言实现顺序栈
    OpenGL 学习,入门程序
  • 原文地址:https://www.cnblogs.com/myswift/p/14887412.html
Copyright © 2020-2023  润新知