zoukankan      html  css  js  c++  java
  • Android 蓝牙 BLE 开发笔记

    最近公司头戴换了一块蓝牙4.0 BLE模块,所以我们Android组要适配 BLE。
    Android BLE 需要 4.3 以上系统,api 还是非常简单的, 第一步就是扫描, 扫描到设备后就可以连接了,
    连接成功后在 onServicesDiscovered 中拿到 Service Characteristic Descriptor 就可以了。
    不过还是遇到了几个小坑
    第一: setCharacteristicNotification 时 onCharacteristicChanged 中收不到回调 原因是 BLE 不能连续执行写操作,必须等前一个
    写完了再写一下个, 所以应该维护一个队列等前一个写完了再写下一个。

    启用通知

    BluetoothGattCharacteristic rxCharacteristic = uartService
            .getCharacteristic(UUID.fromString(BleConst.UUID_RX_CHARACTERISTIC));
    if (rxCharacteristic != null) {
        BluetoothGattDescriptor rxCharacteristicDescriptor = rxCharacteristic
                .getDescriptor(UUID.fromString(BleConst.UUID_RX_CHARACTERISTIC_DESCRIPTOR));
        // 设置 Characteristic 可以接收通知
        gatt.setCharacteristicNotification(rxCharacteristic, true);
        if (rxCharacteristicDescriptor != null) {
            // enable descriptor notification
            rxCharacteristicDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            mBluetoothGatt.writeDescriptor(rxCharacteristicDescriptor);
        }
    }

    第二:蓝牙自动配对
    自动配对就是通过反射去调用 BluetoothDevice 的 createBond 方法

    Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
    createBondMethod.invoke(btDevice);

    第三:蓝牙自动连接
    配对和连接是不一样的,自动配对后还要连接上蓝牙, stackoverflow 查了一些下面的方法可以自动连接 A2DP 和 HFP 两个 profile
    监听 BluetoothDevice.ACTION_BOND_STATE_CHANGED 广播,蓝牙配对成功后调用下面的方法连接上两个 profile 就行了。

    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
        adapter.getProfileProxy(this, new BluetoothProfile.ServiceListener() {
            @Override
            public void onServiceConnected(int profile, BluetoothProfile proxy) {
                try {
                    Log.d(TAG, "a2dp onServiceConnected");
                    Method connect = BluetoothA2dp.class.getDeclaredMethod("connect", BluetoothDevice.class);
                    connect.invoke(proxy, device);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
    
            @Override
            public void onServiceDisconnected(int profile) {
                Log.d(TAG, "a2dp onServiceDisconnected");
            }
        }, BluetoothProfile.A2DP);
    
    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
            adapter.getProfileProxy(this, new BluetoothProfile.ServiceListener() {
                @Override
                public void onServiceConnected(int profile, BluetoothProfile proxy) {
                    try {
                        Log.d(TAG, "hfp onServiceConnected");
                        Method connect = BluetoothHeadset.class.getDeclaredMethod("connect", BluetoothDevice.class);
                        connect.invoke(proxy, device);
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
    
                @Override
                public void onServiceDisconnected(int profile) {
                    Log.d(TAG, "hfp onServiceDisconnected");
                }
            }, BluetoothProfile.HEADSET);

    目前头戴所有按键走的都是蓝牙自定义协议,本来Android是可以用 HID 标准键值的, 但由于 IOS 不支持 HID 所已也走自定义协议。

  • 相关阅读:
    38丨WebSocket:沙盒里的TCP
    Jmeter安装与介绍(一)
    37丨CDN:加速我们的网络服务
    爬虫笔记:xpath和lxml(十二)
    爬虫笔记:Selenium(十一)
    36丨WAF:保护我们的网络服务
    35丨OpenResty:更灵活的Web服务器
    爬虫笔记:抓取qq群成员的头像和昵称生成词云(十)
    Python全栈工程师 (类变量、方法、继承、覆盖)
    Python全栈工程师(面向对象)
  • 原文地址:https://www.cnblogs.com/lesliefang/p/5665991.html
Copyright © 2011-2022 走看看