Android中使用BluetoothKit的操作

最近接触到了和硬件之间的蓝牙交互,有一套Google给的代码,总来的说使用起来太过冗长,封装过程略微复杂。找到一个三方的框架BluetoothKit.

这个蓝牙框架使用起来较为简单。使用方法也较为简洁明了。但是BluetoothKit不能用在经典蓝牙身上,它只支持经典蓝牙的SPP搜索,并不能支持经典蓝牙的连接。而它只支持BLE设备的操作。

  • GATT协议

    在Android4.3(API 18)以上的设备几乎都是BLE。BLE的协议是GATT协议,关于GATT协议,我们需要了解几个关键的词汇:

    ①Profile:一个标准的通信协议,存在于从机中,蓝牙有一些规范的Profile,如:HID(人机交互设备),OVER(基于蓝牙的IPV6组网方式),心率计等。每个Profile中会包含多个Service,每个Service代表从机的一个能力。

    ②Service:在Ble从机中,有很多服务,比如:电量信息服务,系统信息服务等。一个service包含多个characteristic特征值。获取的信息值存放在从机的Profile的Characteristic。然后主机通过characteristic来获取信息数据。所以说,通信最主要的还是Characteristic。

    ③Characteristic:特征。读写内容都是通过Characteristic来进行的。

    ④UUID:统一标识码,Service和Characteristic都有自己的唯一UUID。

    蓝牙协议图大致如下:

 

  • BluetoothKit框架的一些介绍和使用方法

       BluetoothKit提供:连接,读写,通知等接口。

       会自动断开不活跃的蓝牙设备。

 

       BluetoothKit的使用方法:

1.添加依赖  两种方式: ①在gradle中添加compile 'com.inuker.bluetooth:library:1.3.8'   ②导入依赖Library模块

2.添加蓝牙权限

<uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

 

3.扫描蓝牙

private void searchDevice() {
        SearchRequest request = new SearchRequest.Builder().searchBluetoothLeDevice(5000,2).searchBluetoothLeDevice(5000).build();
        ClientManager.getClient().search(request, mSearchResponse);
    }

    private final SearchResponse mSearchResponse = new SearchResponse() {
        @Override
        public void onSearchStarted() {
                 //开始扫描,可以在此加入一些状态设置。以及一些数据清空处理。
                 mDevices.clear();
        }

        @Override
        public void onDeviceFounded(SearchResult device) {
            //监测扫描出的设备是否已经包含在设备数组里
            if (!mDevices.contains(device)) {
                mDevices.add(device);
                //给设备Adapter设值
                mAdapter.setDataList(mDevices);
            }

            if (mDevices.size() > 0) {
                mRefreshLayout.showState(AppConstants.LIST);
            }
        }

        @Override
        public void onSearchStopped() {
            BluetoothLog.w("MainActivity.onSearchStopped");
            mListView.onRefreshComplete(true);
            mRefreshLayout.showState(AppConstants.LIST);
        }

        @Override
        public void onSearchCanceled() {
            BluetoothLog.w("MainActivity.onSearchCanceled");
            mListView.onRefreshComplete(true);
            mRefreshLayout.showState(AppConstants.LIST);
        }
    };

 

4.连接蓝牙

 private void connectDevice() {
        BleConnectOptions options = new BleConnectOptions.Builder()
                .setConnectRetry(3)//重试3次
                .setConnectTimeout(5000)//5s后为连接超时
                .setServiceDiscoverRetry(3)//连接Service重试3次
                .setServiceDiscoverTimeout(5000)//5s后连接'服务'超时
                .build();
        //此处单例出BluetoothClient对象来进行连接操作
        ClientManager.getClient().connect(mMac, options, new BleConnectResponse() {
            @Override
            public void onResponse(int code, BleGattProfile profile) {
                //如果连接没有成功,则重试。
                if (code == REQUEST_SUCCESS) {
                    setGattProfile(profile);
                }else{
                    //检测是否需要连接设备(如果已经连接,则不需要再去连接)
                    connectDeviceIfNeeded();
                }
            }
        });
 }

//获取属性
public void setGattProfile(BleGattProfile profile) {
        List<DetailItem> items = new ArrayList<DetailItem>();
        List<BleGattService> services = profile.getServices();

        for (BleGattService service : services) {
            items.add(new DetailItem(DetailItem.TYPE_SERVICE, service.getUUID(), service.getUUID()));
            List<BleGattCharacter> characters = service.getCharacters();
            for (BleGattCharacter character : characters) {
                items.add(new DetailItem(DetailItem.TYPE_CHARACTER, character.getUuid(), service.getUUID()));
            }
        }
        //将得到的items传递到需要发送信息的位置。DetailItem是service和character的实体。
        //上面我们就提到过,蓝牙间的消息传递获取是根据service的character来做到的。
}

//蓝牙的状态监听
ClientManager.getClient().registerConnectStatusListener(macAddress, mBleConnectStatusListener);
private final BleConnectStatusListener mBleConnectStatusListener = new BleConnectStatusListener() {
    @Override
    public void onConnectStatusChanged(String macAddress, int status) {

        if (status == STATUS_CONNECTED) {
        //蓝牙设备处于连接状态
        } else if (status == STATUS_DISCONNECTED) {
        //蓝牙设备断开
        }

    }
};

//注销蓝牙状态监听
ClientManager.getClient().unregisterConnectStatusListener(macAddress, mBleConnectStatusListener);

 

5.蓝牙硬件通信

private List<DetailItem> mDeviceDetailDataList = new ArrayList<>();
public void setDeviceDetailDataList(List<DetailItem> datas) {
        mDeviceDetailDataList.clear();
        //加入最新的service和character数据
        mDeviceDetailDataList.addAll(datas);
        BaseLoginBean baseLoginBean=loginCheck(mDeviceDetailDataList);
        mService=baseLoginBean.getmService();
        mCharacter=baseLoginBean.getmCharacter();
        //写数据到蓝牙设备。需要得知要操作设备的mac,要操作的service和character,
        //以及要传输给蓝牙设备的信息。以及传输回调。
        ClientManager.getClient().write(macAddress, mService, mCharacter, baseLoginBean.getmBytes(), mWriteRsp);
        //将蓝牙设备传递给我们的信息进行提示返回。需要得知要操作设备的mac,
        //要操作的service和character,以及返回的信息回调。
        ClientManager.getClient().notify(mMac, mService, mCharacter, mNotifyRsp);
}

在读取的时候还有一种read方法。read方法和notify有什么不一样的呢?

notify:有点类似于推送的意思,不管自己去不去读取蓝牙返回给我们的信息。始终都会得到蓝牙返回给的信息。

unnotify:不获取返回信息。

read:用户自己去获取数据,自己要获取的时候才去获取数据。

除此writeNoRsp:凡是带有WRITE_TYPE_NO_RESPONSE标识的,速率比write快2~3倍。建议用于固件升级。

writeDescriptor:对Characteristic的描述,如:范围,计量单位等。同理readDescriptor则是读取。

indicate:和notify类似。 unindicate则是不获取返回信息。

readRssi:读取蓝牙强度。                                              

 6.断开蓝牙

ClientManager.getClient().disconnect(macAddress);

Tips:

1.在某个蓝牙设备disconnect()后,再去调用该蓝牙的disconnect。依然会执行到蓝牙状态回调去。

2.使用notify的时候最好不要在一个界面去复用多次,可能会出现重复调用情况,导致notify回调逻辑混乱。

 

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
BluetoothKit是一款功能强大的Android蓝牙通信框架,支持经典蓝牙和低功耗蓝牙设备混合扫描,提供了一系列简单易用的接口用于低功耗蓝牙设备的连接,数据读写,通知等。 特点 一、支持经典蓝牙和BLE蓝牙混合扫描,支持自定义扫描策略  作为智能家居平台,接入的设备包括经典蓝牙和BLE,因此扫描设备时需要两者混合进行,而设备扫描场景不同,扫描策略也会不一样,因此需要支持扫描策略可配置。 二、充分解决了AndroidBLE兼容性和稳定性问题  Android系统对蓝牙4.0支持得并不完善,有许多bug, BluetoothKit很好地解决了其大部分已知的问题。  三、简单易用,接口简洁明了  BluetoothKit采用异步串行化策略处理所有设备操作,并支持任务超时及出错重试。  技术 一、实现了一个完整的跨进程异步任务队列,支持任务超时、出错重试及防御队列溢出 二、拦截并Hook系统层蓝牙Binder,实现对所有蓝牙设备通信的监控,当同时连接设备数过多时会自动断掉活跃度最低的设备 三、整个框架封装在一个service,可灵活指定service所在进程。通过client与service通信,client可源于多个不同进程,因此适用于多进程架构的app 四、屏蔽了接口异步回调可能持有调用端Activity引用导致的内存泄露 五、利用动态代理自动将所有操作封闭在工作线程,所以整个框架无锁 使用 // 首先,需要按如下方式初始化BluetoothClient: BluetoothClient mClient = BluetoothClient.getInstance(context); // 扫描设备:支持经典蓝牙和BLE设备混合扫描,可自由定制扫描策略如下: SearchRequest request = new SearchRequest.Builder() .searchBluetoothLeDevice(3000, 3) .searchBluetoothClassicDevice(5000) .searchBluetoothLeDevice(2000) .build(); mClient.search(request, new SearchResponse() { @Override public void onSearchStarted() { } @Override public void onDeviceFounded(SearchResult device) { } @Override public void onSearchStopped() { } @Override public void onSearchCanceled() { } }); // 停止蓝牙扫描 mClient.stopSearch(); // BLE设备连接 mClient.connect(MAC, new BleConnectResponse() { @Override public void onResponse(int code, Bundle data) { if (code == REQUEST_SUCCESS) { } } }); // BLE设备断开连接 mClient.disconnect(MAC); // 读取BLE设备 mClient.read(MAC, serviceUUID, characterUUID, new BleReadResponse() { @Override public void onResponse(int code, byte[] data) { if (code == REQUEST_SUCCESS) { } } }); // 写BLE设备 mClient.write(MAC, serviceUUID, characterUUID, bytes, new BleWriteResponse() { @Override public void onResponse(int code) { if (code == REQUEST_SUCCESS) { } } }); // 打开设备通知 mClient.notify(MAC, serviceUUID, characterUUID, new BleNotifyResponse() { @Override public void onNotify(UUID service, UUID character, byte[] value) { } @Override public void onResponse(int code) { if (code == REQUEST_SUCCESS) { } } }); // 关闭设备通知 mClient.unnotify(MAC, serviceUUID, characterUUID, new BleUnnotifyResponse() { @Override public void onResponse(int code) { if (code == REQUEST_SUCCESS) { } } }); // 读取rssi mClient.readRssi(MAC, new BleReadRssiResponse() { @Override public void onResponse(int code, Integer rssi) { if (code == REQUEST_SUCCESS) { } } }); 标签:BluetoothKit
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值