蓝牙开发之传统蓝牙

关于传统蓝牙

传统蓝牙这个概念其实不用细说,相信很多人还对蓝牙配对码这个东西有印象,现在大部分都进行ble开发了,而且传统蓝牙不支持与ios互传数据
这里主要讲解思路和概念,和小白扫盲,我当初公司做蓝牙的时候,对蓝牙整体的概念就比较懵,以为ble就是传统蓝牙,后来查阅资料多了,才逐渐分清和了解二者代码开发

本人demo地址,这个demo主要以做实验为主,有多连接,自动配对,通信,所以代码不是特别适合新手看,嘿嘿,主要是懒,所有想实验的功能都是在基本代码上直接加上去的,所以你懂得~
github上demo地址

蓝牙通信

本质还是socket通信

  • 服务端启动监听
  • 客户端请求
  • 连接确认

蓝牙通信两边的 UUID 必须是一样的,这是一个服务的唯一标识,而且这个 UUID 的值必须是 00001101-0000-1000-8000-00805F9B34FB。
为什么呢?因为这个是 Android 的 API 上面说明的,用于普通蓝牙适配器和 Android 手机蓝牙模块连接的,请大家自己看一下 Android 有关 bluetooth的 API。

主要涉及四个类

  • BluetoothAdapter
    这个类代表蓝牙适配器,并且是所有蓝牙交互的入口点,通过这个类,我们可以发现其他的蓝牙设备,并且打开蓝牙功能等;

  • BluetoothDevice
    代表一个蓝牙设备,可以通过该类活设备名称、设备地址、配对状态等。

  • BluetoothSocket
    socket连接的管理类,可以获取并通过InputStream OutputStream与另一个蓝牙设备交换数据

  • BluetoothServerSocket
    是一个开放的服务器套接字,侦听传入请求(类似于一个TCP ServerSocket);
    为了连接两个Android设备,设备必须用这个类打开一个服务器套接字;
    当一个远程蓝牙设备请求连接到这个设备,如果请求的连接被接受,那么BluetoothServerSocket将返回一个已经连接的BluetoothSocket对象。

以上较官方的解释,其实熟悉socket开发的应该知道,socket就是C/S的开发模式,所以需要一个服务端来监听连接也就是accept

蓝牙基本操作

打开蓝牙

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    if (mBluetoothAdapter == null){
        Log.d(TAG,"设备蓝牙无法使用");
        return;
    }
    if (!mBluetoothAdapter.isEnabled()){
        //若没打开则打开蓝牙
        mBluetoothAdapter.enable();
    }

使设备可以被周围的设备搜索到

Intent intentDiscov = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
// 让当前蓝牙设备可见,默认值为120秒,超过300秒的请求将被限制
intentDiscov.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, mDiscoverableTime);
((Activity)mContext).startActivityForResult(intentDiscov, RESULT_DISCOVERABLE);

客户端蓝牙连接及通信

注册广播,展示搜索到的设备,用户选择点击获取设备的mac地址和设备名称,使用mac地址连接

简单说就是,发现->配对->连接
这个代码就不在这里展示了,直接看demo吧

通过蓝牙地址获取远程设备对象

mDevice = mBluetoothAdapter.getRemoteDevice(mBlueToothAddress);

客户端线程中连接socket

mClientThread = new ClientThread();
mClientThread.start();

使用设备对象和uuid获取socket对象,并连接,出现io异常呢个就说明连接失败

mClientSocket = mDevice.createRfcommSocketToServiceRecord(mUuid);
mClientSocket.connect();

// 启动接收数据
mReadThread = new ReadThread(mClientSocket);
mReadThread.start();

客户端接收线程中

inputStream = socket.getInputStream();
   while (true) {
       if ((bytes = inputStream.read(buffer)) > 0) {
            byte[] bufData = new byte[bytes];
            for (int i = 0; i < bytes; i++) {
                bufData[i] = buffer[i];
            }
                String msg = new String(bufData);
                //发送给界面更新UI
                sendHandlerMsg(MESSAGE, msg);
        }
    }

客户端发消息

发消息就是socket获取输出流

 // 判断socket是服务器获得的还是客户端获得的
    if (null != mServerSocket) {
        outputStream = mServerSocket.getOutputStream();
        outputStream.write(message.getBytes());
    }

关闭客户端线程和流

private void shutdownClient() {
    Log.e(TAG, "shutdownClient()");

    if (mClientThread != null) {
        mClientThread.interrupt();
        mClientThread = null;
    }
    if (mReadThread != null) {
        mReadThread.interrupt();
        mReadThread = null;
    }
    if (mClientSocket != null) {
        try {
            mClientSocket.close();
            mClientSocket = null;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

蓝牙自动连接

将你的设备设置成默认密码,如0000或1111,或者无密码

就是在广播搜索到你的设备时,主动连接,并且屏蔽广播,使用默认的密码或者无配对码

搜索设备名,如果mac地址可以预知,直接连mac地址比较好

ClsUtils.setPairingConfirmation(btDevice.getClass(), btDevice, true);
abortBroadcast();

服务端蓝牙连接代码

初始化蓝牙对象及使设备可被发现,直接启动线程

线程中直接监听客户端的连接

PROTOCOL_SCHEME_RFCOMM是常量随便设置

mBluetoothServer = 
mBluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM, mUuid);

获取socket对象,并启动接收数据的线程即可,代码同客户端

if (mServerSocket == null) {
    mServerSocket = mBluetoothServer.accept();
    // 启动接受数据
    mReadThread = new ReadThread(mServerSocket);
    mReadThread.start();
}

蓝牙服务端一对多通信

蓝牙服务端一对多通信,就是监听到连接时,再获取一个socket

if (mServerSocket == null) {
        mServerSocket = mBluetoothServer.accept();
        // 启动接受数据
        mReadThread = new ReadThread(mServerSocket);
        mReadThread.start();
}
if (mSeverSocketTwo == null) {
        mSeverSocketTwo = mBluetoothServer.accept();
        // 启动接受数据
        mReadThreadTwo = new ReadThread(mSeverSocketTwo);
        mReadThreadTwo.start();
}

在接收发送数据时,同时操作两个socket对象即可,释放也需要都释放掉

蓝牙客户端一对多通信

客户端一对多与服务端一对多类似创建多个socket,多读收数据的线程

    原文作者:android老男孩
    原文地址: https://www.jianshu.com/p/8094ae3660a5
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞