Android BLE 开发问题汇总

一 设备连接太慢问题 .

1. 效果最明显的方法:

将 connectGATT()方法的第二个参数设置成false.如下所示.

// 第二个参数的作用如下 : 
// Whether to directly connect to the remote device (false) or to
// automatically connect as soon as the remote device becomes available (true).

device.connectGatt(mContext,false,mGattCallback)

二 相关回调问题.

Android BLE 相关的 API 回调都是在发送该操作请求的线程中执行的线程中执行的.
因此不要让该线程阻塞,否则的话.很多回调都无法执行.

比如 :

// 发送数据,写特征值. 会触发 Android 的 onCharacteristicWirte() 回调方法.
gatt.writeCharacteristic(characteristic)

// 回调方法onCharacteristicWirte执行在上面代码所在的线程中.
// 因此如果在代码中有阻塞操作.比如
while(true){
    // ...
}
// 就会造成onCharacteristicWirte回调方法无法执行.产生各种不正常的现象.

三 Android 数据发送问题.

1. 发送长度问题.

在 Android 5.0 以前单次发送/接收数据的最大长度是 20 字节 .
因此对于数据量较大的数据需要进行分包发送处理 . 特别需要注意的是如果BLE外设
单次发送的数据量大于 20 字节, Android 只能接收前20个字节的数据.
后面的数据将会丢失 .

2. 分包发送

分包发送要注意不要在当前线程做阻塞处理.否则会出现不可预知的情况. 并且一定要在上次发送数据成功写入(onCharacteristicWrite()回调执行)的情况下再去进行第二次写操作.否则第二次写操作将会失败.

3. 分包发送示例.

// 发送数据接口. 
private int sendData2DeviceInner2(final byte[] data){
    LogUtils.e(TAG,"设置发送参数 : " + FunctionTools.byte2HexString(data));
    mSendDataPackage.initSendTask(Arrays.copyOf(data,data.length));
    // 发送一次数据.
    new Thread(sendDataPackageTask).start();
    return RES_BLE_SUCCESS;
}
 // 写数据.
private boolean sendDataInner(byte[] data){
    LogUtils.e(TAG,"sendDataInner当前线程 : " + Thread.currentThread().getId());
    mService = mCurBluetoothGatt.getService(SERVICE_UUID);
    if (!isObjectNull(mBlxService)) {
        mWriteCharacteristic = mBlxService.getCharacteristic(CHARACTERISTIC_WRITE_UUID);
    }
    if (!isObjectNull(mWriteCharacteristic)) {
        mWriteCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
        boolean res = mWriteCharacteristic.setValue(data);
        boolean res1 = mCurBluetoothGatt.writeCharacteristic(mWriteCharacteristic);
        if (res&res1)
            startDevComTimer();
        return res & res1;
    }else{
        LogUtils.e(TAG,"写特征值为空");
        return false;
    }
}
// 待发送数据缓存类.
private sendDataPackage mSendDataPackage = new sendDataPackage();
private class sendDataPackage {
        // 发送数据
        int sendTotalLen = 0;
        int sendIndex = 0;
        byte[] sendBuffer = new byte[0];
        public void clearSendFlags(){
            sendTotalLen = 0;
            sendIndex = 0;
            sendBuffer = new byte[0];
        }
        public void initSendTask(final byte[] data){
            sendTotalLen = data.length;
            sendIndex = 0;
            sendBuffer = data;
        }
        public byte[] getOnceBuffer(){
            if (sendBuffer.length == 0)
                return new byte[0];
            int len = MAX_SEND_BYTES_COUNT;
            if (sendTotalLen - sendIndex < MAX_SEND_BYTES_COUNT)
                len = sendTotalLen - sendIndex;
            // 更新 Index
            sendIndex += len;

            return Arrays.copyOfRange(sendBuffer,sendIndex - len,sendIndex);
        }
        public boolean needSend(){
            if (sendBuffer.length == 0 || sendTotalLen == 0)
                return false;
            if (sendTotalLen == sendIndex )
                return false;
            return true;
        }
}
// 发送数据任务.    
private Runnable sendDataPackageTask = new Runnable() {
        @Override
        public void run() {
            LogUtils.d(TAG,">>>>>>>>>> 发送数据");
            if (mSendDataPackage.needSend()){
                if (!sendDataInner(mSendDataPackage.getOnceBuffer())){
                    // 发送数据失败
                    // TODO .......清理标志位
                }
            }
        }
};
// 写数据回调实现代码
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
    super.onCharacteristicWrite(gatt, characteristic, status);
    if (status == BluetoothGatt.GATT_SUCCESS) {
        // 写成功
        if (mSendDataPackage.needSend())
            new Thread(sendDataPackageTask).start();
        }
        else
            // 写失败....
}

四 Android 中重复连接BLE导致设备直接返回STATE_DISCONNECTED的解决办法

问题描述

通过使用if(gatt==null)来判断gatt是否被创建过,如果创建过就使用gatt.connect(),重新建立连接,但是在这种情况下测试的结果是重新连接需要花费很长的时间。

解决办法

解决办法是通过gatt = device.connectGatt(this, false, gattCallback);
建立一个新的连接对象,很明显这样的速度要比上一种方法快很多;

问题描述

但是,多次创建gatt连接对象的直接结果是创建过6个以上gatt后就会再也连接不上任何设备,原因应该是android中对BLE限制了同时连接的数量为6个.

解决办法

在每一次重新连接时都执行一次gatt.close(),关闭上一个连接。有人说为什么不在gatt.disconnect();后加一条gatt.close();呢,原因是如果立即执行gatt.close();会导致gattCallback无法收到STATE_DISCONNECTED的状态。当然,最好的办法是在gattCallback收到STATE_DISCONNECTED后再执行gatt.close();这样逻辑上会更清析一些。

参考 :

链接 : http://bbs.eeworld.com.cn/thread-438571-1-1.html

五 分包发送数据出错问题 .

问题 :

有些蓝牙芯片接收数时出现TX的数据被覆盖的问题.导致接收到的数据个别字节发生错误. 因为蓝牙芯中两帧数据中间是需要间隔的.

解决方法 :

  1. 可以在Android端在分包发送时增加延时操作(100ms较好) .
  2. 在COS程序中增加延时操作(推荐使用的方法).
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容