谷歌官方BLEdemo详解

** 安卓开发中或多或少会接触到蓝牙部分,像一些智能家居,蓝牙手环,还有一些串口数据传输的设备都和蓝牙相关,面试的时候有的公司也会问到一些蓝牙相关的问题,这里我来说说关于低功耗蓝牙的一些相关知识,这些知识也是我在网上查阅总结的。在百度上一搜低功耗蓝牙的帖子很多,但都讲的不是很全面,让人知其然不知其所以然。这里我就从简单的开始先分析一些谷歌的demo的代码,看看BLE蓝牙是怎么建立通信的,只要掌握了BLE蓝牙通信那么再将发送接收的数据处理一下就ok了,当然光看这一篇帖子不一定会完全把低功耗蓝牙弄懂,兴许会遇到一些坑,但是坚持下去始终会弄懂的;**

这是网上提供的Android 蓝牙4.0 ble 官方 demo

  • App的界面图
app界面.jpg

App的界面很简单就两个界面

代码主要包含四个类

  • DeviceScanActivity类(展示手机扫描到的BLE蓝牙);

  • DeviceControlActivity类(BLE操作控制台);

  • BluetoothLeService类(通过服务来管理蓝牙,其中通过广播来于DeviceControlActivity类通信)

  • SampleGattAttributes类(不同种类的UUID)

DeviceScanActivity类的功能:

这个类之间继承ListActivity,顾名思义,它可能是一个展示列表,细看代码,它切实是一个列表展示类,这个类的主要作用就是展示手机扫描到的可用蓝牙;点击选择的BLE后将BLE的属性(名称和ID)传递到DeviceControlActivity类;

该类的主要流程就是 在onCreate方法中判断手机是否支持BLE,然后初始化蓝牙适配器,最后就是手机的权限适配(蓝牙需要定位的权限)
在onResume方法中检测蓝牙是否开启,没有开启那就开启蓝牙,不开启的话那么就触发onActivityResult方法则finish()关闭app,开启蓝牙的话则
开启扫描 scanLeDevice(true); true为开启扫描 false为关闭扫描;在扫描的方法scanLeDevice中可以看到通过handler计时扫描十秒钟;
开启扫描后将会回调 mLeScanCallback 对象;在这个对象中重写了onLeScan方法,这个方法中的参数onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord)中device则为蓝牙设备属性;将蓝牙设备属性展示到列表中,通listview监听选中 的蓝牙跳转到DeviceControlActivity类;

DeviceControlActivity类中要功能:

开启服务BluetoothLeService,接收服务传过来的蓝牙数据;里面有几个重要的类部类:
ServiceConnection(BinderService的返回数据接收类);BluetoothGattCallback(广播,接收服务发送过来的消息); ExpandableListView.OnChildClickListener(这是一个list二级列表的监听类);里面还有一个重要的方法就displayGattServices(listview的适配器);

该类的主要流程:注册广播并接收,在onCreate中对一些控件的初始化,通过intent传值获取到蓝牙的名称和ID,然后启动服务;在ServiceConnection内部类中得到服务的对象 mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();在 onResume方法中通过服务的对象建立蓝牙的连接,注意 蓝牙连接后还并不能通信,建立通信使用通过UUID的;蓝牙建立连接后会触发广播action为BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED方法,在这个方法中通过调用displayGattServices方法展示蓝牙的UUID的数据,可以看到蓝牙有很多UUID,其实UUID是分可读的,可写的,和可读可写的,这应该是蓝牙厂家写好的固件;在app上我们可以挨个的点击不同的UUID将会建立不同的连接,其中就有一种连接可以信;点击UUID将会OnChildClickListener()方法,里面的逻辑主要就是开启蓝牙的读取功能和开启蓝牙的的通知功能
mBluetoothLeService.setCharacteristicNotification(mNotifyCharacteristic, false);
mBluetoothLeService.readCharacteristic(characteristic);

BluetoothLeService类主要功能:

就是通过UUID建立蓝牙通讯,readCharacteristic()开启蓝牙读的功能,setCharacteristicNotification()开启蓝牙或禁用通知的功能;getSupportedGattServices()只有在成功完成之后才会调用此函数。在连接的设备上检索受支持的有关协定服务列表,里面没有蓝牙写数据的方法,要自己写;

该类的主要流程就是通过DeviceControlActivity类传过来的蓝牙ID建立蓝牙连接
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
其中里面有一个非常重要的类mGattCallback回调,这里面重写了几个方法
onConnectionStateChange()蓝牙连接状态改变的回调;
onServicesDiscovered()服务发现的回调在这个方法中可以建立蓝牙的连接
onCharacteristicRead()蓝牙的特征;
onCharacteristicChanged()Characteristic状态改变的回调
onCharacteristicWrite)()Characteristic写操作的结果回调:

这里说一下重点:通过上面的解释还是会知其然不知其所以然。

蓝牙读数据有两种方法:

一种是调用readCharacteristic()方法 开启读 ,一种是通过通知来读 setCharacteristicNotification方法;

通过uuid 读某个Characteristic

开启读

mBluetoothLeService.readCharacteristic(characteristic);

public void readCharacteristic(BluetoothGattCharacteristiccharacteristic) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return;
        }
        mBluetoothGatt.readCharacteristic(characteristic);
}

如果成功,数据会在下面的方法回调中传进来

public void  onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }

还可以通过通知的回调方法读取数据 这种方式不用手机去轮询地读设备上的数据。

 //设置true为启用通知,false反之
  setCharacteristicNotification(mNotifyCharacteristic, true);

有消息来后会回调方法
public void  onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
        }

写数据就更简单了
通过UUID获取到BluetoothGattCharacteristic

BluetoothGattCharacteristic alertLevel =linkLossService.getCharacteristic(UUID.fromString("49535343-8841-43f4-a8d4-ecbe34729bb3"));
alertLevel.setValue(values_on);
status = mBluetoothGatt.writeCharacteristic(alertLevel);

status如果为true,表示写操作已经成功执行,BluetoothGattCallback抽象类的一个方法会被执行,如果刚好你又重写了这个方法,就可以打印一些消息了

public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristiccharacteristic, int status){

}

官方的demo没有用发送数据的代码,接收数据也是16进制,这个需要自己按实际情况修改代码或是在网上找一些demo有收发功能的,开放项目复杂多变,这里很难以偏概全,就不一一展示了;

总结:蓝牙收发数据每次最多20个字节,这就要对接收的数据进行拼接,截取了;发送数据也是以20个字节为单位,一段一段发送;蓝牙对于有些人来说也许会很难, 但是琢磨久了就会看懂的;

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

推荐阅读更多精彩内容