码迷,mamicode.com
首页 > 移动开发 > 详细

蓝牙通信测试app之蓝牙通信

时间:2021-06-16 17:45:58      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:阻塞   res   his   tac   循环读取   exce   使用   exception   socket   

蓝牙通信开发流程

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

  • 服务端:使用的是 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();
    
  • 然后调用连接线程,请求连接服务端

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

蓝牙通信测试app之蓝牙通信

标签:阻塞   res   his   tac   循环读取   exce   使用   exception   socket   

原文地址:https://www.cnblogs.com/myswift/p/14887412.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!