Android蓝牙使用详解(普通蓝牙)2

简介: Android蓝牙使用详解(普通蓝牙)

接上一篇

进行设备连接

  引用官方的文档

要在两台设备上的应用之间创建连接,必须同时实现服务器端和客户端机制,因为其中一台设备必须开放服务器套接字,而另一台设备必须发起连接(使用服务器设备的 MAC 地址发起连接)。 当服务器和客户端在同一 RFCOMM 通道上分别拥有已连接的 BluetoothSocket 时,二者将被视为彼此连接。

由上面的引用可知,要想创建两个应用之间的连接,必须同时实现服务器端和客户端机制,下面,分别介绍怎样实现为服务器端和客户端机制。

实现为服务器

当您需要连接两台设备时,其中一台设备必须通过保持开放的 BluetoothServerSocket 来充当服务器。 服务器套接字的用途是侦听传入的连接请求,并在接受一个请求后提供已连接的 BluetoothSocket。 从 BluetoothServerSocket 获取 BluetoothSocket 后,可以(并且应该)舍弃 BluetoothServerSocket,除非您需要接受更多连接。

下面是作为服务端的代码

private class AcceptThread extends Thread {
        private final BluetoothServerSocket mmServerSocket;
        public AcceptThread() {
            BluetoothServerSocket tmp = null;
            try {
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME,
                        MY_UUID);
            } catch (IOException e) {
            }
            mmServerSocket = tmp;
            mState = STATE_LISTEN;
        }
        public void run() {
            setName("AcceptThread");
            BluetoothSocket socket = null;
            while (mState != STATE_CONNECTED) {
                try {
                    socket = mmServerSocket.accept();
                } catch (IOException e) {
                    break;
                }
                if (socket != null) {
                    synchronized (BluetoothService.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) {
                                }
                                break;
                        }
                    }
                }
            }
        }
        public void cancel() {
            try {
                mmServerSocket.close();
            } catch (IOException e) {
            }
        }
    }

这里解释一下,为什么要新开一个线程来作为服务端,因为通过调用 accept()这是一个阻塞调用。

注意:mAdapter.listenUsingRfcommWithServiceRecord(NAME,MY_UUID);中的MY_UUID必须与客服端连接时的UUID一致。

总结一下作为服务端的步骤:

  1. 通过调用 listenUsingRfcommWithServiceRecord(String, UUID) 获取 BluetoothServerSocket
  2. 通过调用 accept() 开始侦听连接请求。
  3. 如果不想让更多的设备连接,则在连接后调用close()关闭。

实现为客户端

  先看下作为客户端的代码

 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) {
            }
            mmSocket = tmp;
            mState = STATE_CONNECTING;
        }
        public void run() {
            setName("ConnectThread");
            mAdapter.cancelDiscovery();
            try {
                mmSocket.connect();
            } catch (IOException e) {
                try {
                    mmSocket.close();
                } catch (IOException e2) {
                }
                return;
            }
            synchronized (BluetoothService.this) {
                mConnectThread = null;
            }
            connected(mmSocket, mmDevice);
        }
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
            }
        }
    }

这里有一点需要注意,也是官方文档中强调的

**注:**在调用 connect() 时,应始终确保设备未在执行设备发现。 如果正在进行发现操作,则会大幅降低连接尝试的速度,并增加连接失败的可能性。

因此,在进行连接之前必须调用mAdapter.cancelDiscovery();来关闭查找设备。这里总结一下作为客户端的步骤:

  1. 使用 BluetoothDevice,通过调用 createRfcommSocketToServiceRecord(UUID) 获取 BluetoothSocket。(这里的UUID必须与服务端的保持一致)
  2. 通过调用 connect() 发起连接。

  如果两台设备之前尚未配对,则在连接过程中,Android 框架会自动向用户显示配对请求通知或对话框,如下图所示。

4c7a6bc03e46aa2f594c7230f9e592e.png

进行配对之后就可以进行通信及数据的传输了。

数据传输

  通过上面的几步,这时已经可以实现设备之间的连接了。下面说一下设备之间的通信。

  其实在两台设备连接成功后,每台设备都会有一个已连接的 BluetoothSocket。我们则可以利用 BluetoothSocket,来进行数据的传输。看代码

 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;
            // 获取BluetoothSocket的input and output streams
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "temp sockets not created", e);
            }
            mmInStream = tmpIn;
            mmOutStream = tmpOut;
            mState = STATE_CONNECTED;
        }
        public void run() {
            Log.i(TAG, "BEGIN mConnectedThread");
            byte[] buffer = new byte[1024];
            int bytes;
            while (mState == STATE_CONNECTED) {
                try {
                    bytes = mmInStream.read(buffer);
                    Log.d(TAG, "已经连接");
                    mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
                            .sendToTarget();
                } catch (IOException e) {
                    Log.e(TAG, "disconnected", e);
                    break;
                }
            }
        }
        //写数据
        public void write(byte[] buffer) {
            try {
                mmOutStream.write(buffer);
    //发送消息到主线程
              mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, buffer)
                        .sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "Exception during write", e);
            }
        }
        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "close() of connect socket failed", e);
            }
        }
    }

从上面代码中可以看到,首先是通过BluetoothSocket来拿到InputStream和OutputStream,然后利用readwrite方法来读取和写入数据。

结束语

  本文的内容是基于普通蓝牙进行描述的,主要讲解了怎样操作蓝牙及进行设备间的通讯。不过现在好多都是在BLE蓝牙设备间进行通讯了,当然,我也会针对BLE蓝牙设备在写一篇文章,本文就是为后面的BLE蓝牙讲解做准备的。

  文中都是截取的主要代码,要获取全部源码请点击这里

相关文章
|
6月前
|
JavaScript Java Android开发
uniapp通过蓝牙传输数据 (安卓)
uniapp通过蓝牙传输数据 (安卓)
305 1
|
6月前
|
XML 物联网 API
Android Ble蓝牙App(五)数据操作
Android Ble蓝牙App(五)数据操作
633 0
|
6月前
|
Android开发
【Android App】蓝牙的设备配对、音频传输、点对点通信的讲解及实战(附源码和演示 超详细)
【Android App】蓝牙的设备配对、音频传输、点对点通信的讲解及实战(附源码和演示 超详细)
1254 0
|
3月前
|
Android开发
Android 配置蓝牙遥控器键值
本文详细介绍了Android系统中配置蓝牙遥控器键值的步骤,包括查看设备号、配置键位映射文件(kl文件)、部署kl文件以及调试过程,确保蓝牙遥控器的按键能正确映射到Android系统对应的按键功能。
145 1
|
6月前
|
Android开发
Android获取蓝牙设备列表的方法
Android获取蓝牙设备列表的方法
534 5
|
6月前
|
定位技术 Android开发
Android 12蓝牙报java.lang.SecurityException: Need android.permission.BLUETOOTH_CONNECT permission
Android 12蓝牙报java.lang.SecurityException: Need android.permission.BLUETOOTH_CONNECT permission
238 1
|
6月前
|
Android开发
Android监听蓝牙广播
Android监听蓝牙广播
63 1
|
6月前
|
XML 物联网 API
Android Ble蓝牙App(二)连接与发现服务
Android Ble蓝牙App(二)连接与发现服务
205 1
|
6月前
|
物联网 Android开发
Android Ble蓝牙App(七)扫描过滤
Android Ble蓝牙App(七)扫描过滤
184 0
|
6月前
|
物联网 Android开发
Android Ble蓝牙App(六)请求MTU与显示设备信息
Android Ble蓝牙App(六)请求MTU与显示设备信息
350 0
下一篇
无影云桌面