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 所已也走自定义协议。

 

posted @ 2016-07-13 10:38  LeslieFang  阅读(4033)  评论(0编辑  收藏  举报