Android BLE开发之Android手机与BLE终端通信

 

 

蓝牙开发者门户:http://developer.bluetooth.cn/libs/Cn/Specifi/GATT/2014/0117/56.html

 

最近穿戴设备发展得很火,把相关技术也带旺了,其中一项是BLE(Bluetooth Low Energy)。BLE是蓝牙4.0的核心Profile,主打功能是快速搜索,快速连接,超低功耗保持连接和传输数据,弱点是数据传输速率低,由于BLE的低功耗特点,因此普遍用于穿戴设备。Android 4.3才开始支持BLE API,所以请各位客官把本文代码运行在蓝牙4.0和Android 4.3及其以上的系统,另外本文所用的BLE终端是一个蓝牙4.0的串口蓝牙模块。

PS:我的i9100刷了4.4系统后,竟然也能跟BLE蓝牙模块通信。


BLE分为三部分Service、Characteristic、Descriptor,这三部分都由UUID作为唯一标示符。一个蓝牙4.0的终端可以包含多个Service,一个Service可以包含多个Characteristic,一个Characteristic包含一个Value和多个Descriptor,一个Descriptor包含一个Value。一般来说,Characteristic是手机与BLE终端交换数据的关键,Characteristic有较多的跟权限相关的字段,例如PERMISSION和PROPERTY,而其中最常用的是PROPERTY,本文所用的BLE蓝牙模块竟然没有标准的Characteristic的PERMISSION。Characteristic的PROPERTY可以通过位运算符组合来设置读写属性,例如READ|WRITE、READ|WRITE_NO_RESPONSE|NOTIFY,因此读取PROPERTY后要分解成所用的组合(本文代码已含此分解方法)。


本文代码改自Android 4.3 Sample的BluetoothLeGatt,把冗余代码去掉,获取的BLE设备信息都通过Log,还有一些必要的读写蓝牙方法,应该算是简化到大家一看就可以懂了。本文代码可以到http://download.csdn.net/detail/hellogv/7228819下载。接下来贴出本文运行的结果,首先是连接BLE设备后,枚举出设备所有Service、Characteristic、Descriptor,并且手机会往Characteristic uuid=0000ffe1-0000-1000-8000-00805f9b34fb写入“send data->”字符串,BLE终端收到数据通过串口传到PC串口助手(见PC串口助手的截图):

04-21 18:28:25.465: E/DeviceScanActivity(12254): -->service type:PRIMARY
04-21 18:28:25.465: E/DeviceScanActivity(12254): -->includedServices size:0
04-21 18:28:25.465: E/DeviceScanActivity(12254): -->service uuid:00001800-0000-1000-8000-00805f9b34fb
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char uuid:00002a00-0000-1000-8000-00805f9b34fb
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char property:READ
04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char uuid:00002a01-0000-1000-8000-00805f9b34fb
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char property:READ
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char uuid:00002a02-0000-1000-8000-00805f9b34fb
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char property:READ|WRITE|
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char uuid:00002a03-0000-1000-8000-00805f9b34fb
04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char property:READ|WRITE|
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char uuid:00002a04-0000-1000-8000-00805f9b34fb
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char property:READ
04-21 18:28:25.475: E/DeviceScanActivity(12254): -->service type:PRIMARY
04-21 18:28:25.475: E/DeviceScanActivity(12254): -->includedServices size:0
04-21 18:28:25.475: E/DeviceScanActivity(12254): -->service uuid:00001801-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char uuid:00002a05-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char property:INDICATE
04-21 18:28:25.480: E/DeviceScanActivity(12254): -------->desc uuid:00002902-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW
04-21 18:28:25.480: E/DeviceScanActivity(12254): -->service type:PRIMARY
04-21 18:28:25.480: E/DeviceScanActivity(12254): -->includedServices size:0
04-21 18:28:25.480: E/DeviceScanActivity(12254): -->service uuid:0000ffe0-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char uuid:0000ffe1-0000-1000-8000-00805f9b34fb
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char permission:UNKNOW
04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char property:READ|WRITE_NO_RESPONSE|NOTIFY|
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc uuid:00002902-0000-1000-8000-00805f9b34fb
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc uuid:00002901-0000-1000-8000-00805f9b34fb
04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW
04-21 18:28:26.025: E/DeviceScanActivity(12254): onCharRead BLE DEVICE read 0000ffe1-0000-1000-8000-00805f9b34fb -> 00

这里红字是由BluetoothGattCallback的onCharacteristicRead()回调而打出Log




以下Log是PC上的串口工具通过BLE模块发送过来,由BluetoothGattCallback的 onCharacteristicChanged()打出Log
04-21 18:30:18.260: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:18.745: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.085: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.350: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.605: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:19.835: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.055: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.320: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.510: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:20.735: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone
04-21 18:30:21.000: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone

 

android4.3 nei内置了ble并为上层app提供相应的接口来使用BLE功能。


BLE主要涉及的协议及术语:


GenericAttribute Profile (GATT)

BLE上层的协议都是基于GATT,它是一个通用的规范,通过BLE连接发送/接收属性值。


bluetoothSIG定义了很多的ble协议。


AttributeProtocol (ATT)

GATT是建立在ATT之上。也被称为GATT/ATT


ATT运行在ble设备上,所以被优化,尽可能的占用较少的字节。


每一个属性被指定一个UUID,通过ATT传输的属性被格式化位特性(characteristics)或服务(services)。


Characteristic

一个特性包含一个单一的值和0-n个描述符(Descriptor)来描述这个特性值。一个特性可以被看作一个类型。


Descriptor

描述符被定义为属性,这些属性用来描述特性的值。

例如:规定特性值的取值范围,特性值的单位等


Service

服务是一组特性的集合。例如:“心率检测”服务包含“心速测量”的特性。


角色和职责

中心与外围:被应用于BLE连接本身,中心角色设备扫描/寻找广播,外围设备角色发出广播。


GATTserver vs. GATT client

这个决定了两个设备在建立连接之后如何交互。


android手机和BLE设备的区别:手机支持中心角色(centralrole),BLE设备支持peripheralrole


一旦建立连接,他们就开始相互传输gatt数据,根据传输的数据的种类其中的一个可能作为服务器。

如果BLE设备想报告数据给手机,它可能让BLE设备的传感器作为服务器。如果BLE设备准备接收来自手机的数据,手机的传感器就作为服务端。


以上例子说明:androidappGATT clientGATTclientGATT server 获取数据。也可以设计android app作为GATTserver


BLE权限:

<span style="font-family:DejaVu Sans Mono,monospace;"><uses-permission android:name="android.permission.BLUETOOTH"/></span>
<span style="font-family:DejaVu Sans Mono,monospace;"><uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/></span>
<span style="font-family:DejaVu Sans Mono,monospace;"><uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/></span>



如果想把app提供给不支持BLE的设备需要设置android:required="fasle",然后在运行时进行判断:

<span style="color:#0000ff;"><span style="font-family:DejaVu Sans Mono,monospace;">if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {</span></span>
<span style="color:#0000ff;">    <span style="font-family:DejaVu Sans Mono,monospace;">Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();</span></span>
<span style="color:#0000ff;">    <span style="font-family:DejaVu Sans Mono,monospace;">finish();</span></span>
<span style="color:#0000ff;"><span style="font-family:DejaVu Sans Mono,monospace;">}</span></span>



设置BLE


1:获取BluetoothAdapter


BluetoothAdapter是所有蓝牙功能所必需的,整个系统只有一个BluetoothAdapter,获取BluetoothAdapter之后就可以进行各种蓝牙的操作了。

<span style="font-family:DejaVu Sans Mono,monospace;">// Initializes Bluetooth adapter.</span>
<span style="font-family:DejaVu Sans Mono,monospace;">final BluetoothManager bluetoothManager =</span>
        <span style="font-family:DejaVu Sans Mono,monospace;">(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);</span>
<span style="font-family:DejaVu Sans Mono,monospace;">mBluetoothAdapter = bluetoothManager.getAdapter();</span>


2:启动蓝牙

通过isEnabled()判断是否启动,如果没有启动,通过下面的方式启动:

<span style="font-family:DejaVu Sans Mono,monospace;">private BluetoothAdapter mBluetoothAdapter;</span>
<span style="font-family:DejaVu Sans Mono,monospace;">...</span>
<span style="font-family:DejaVu Sans Mono,monospace;">// Ensures Bluetooth is available on the device and it is enabled. If not,</span>
<span style="font-family:DejaVu Sans Mono,monospace;">// displays a dialog requesting user permission to enable Bluetooth.</span>
<span style="font-family:DejaVu Sans Mono,monospace;">if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);</span>
<span style="font-family:DejaVu Sans Mono,monospace;">}</span>


3:查找BLE设备

通过startLeScan查找LE设备,并实现LeScanCallback作为参数。

注意事项:1:一旦找到所查找的设备,立即停止扫描

2:设置扫描超时,避免循环扫描。


<span style="font-family:DejaVu Sans Mono,monospace;">public class DeviceScanActivity extends ListActivity {</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">private BluetoothAdapter mBluetoothAdapter;</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">private boolean mScanning;</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">private Handler mHandler;</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">// Stops scanning after 10 seconds.</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">private static final long SCAN_PERIOD = 10000;</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">...</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">private void scanLeDevice(final boolean enable) {</span>
        <span style="font-family:DejaVu Sans Mono,monospace;">if (enable) {</span>
            <span style="font-family:DejaVu Sans Mono,monospace;">// Stops scanning after a pre-defined scan period.</span>
            <span style="font-family:DejaVu Sans Mono,monospace;">mHandler.postDelayed(new Runnable() {</span>
                <span style="font-family:DejaVu Sans Mono,monospace;">@Override</span>
                <span style="font-family:DejaVu Sans Mono,monospace;">public void run() {</span>
                    <span style="font-family:DejaVu Sans Mono,monospace;">mScanning = false;</span>
                    <span style="font-family:DejaVu Sans Mono,monospace;">mBluetoothAdapter.stopLeScan(mLeScanCallback);</span>
                <span style="font-family:DejaVu Sans Mono,monospace;">}</span>
            <span style="font-family:DejaVu Sans Mono,monospace;">}, SCAN_PERIOD);</span>
            <span style="font-family:DejaVu Sans Mono,monospace;">mScanning = true;</span>
            <span style="font-family:DejaVu Sans Mono,monospace;">mBluetoothAdapter.startLeScan(mLeScanCallback);</span>
        <span style="font-family:DejaVu Sans Mono,monospace;">} else {</span>
            <span style="font-family:DejaVu Sans Mono,monospace;">mScanning = false;</span>
            <span style="font-family:DejaVu Sans Mono,monospace;">mBluetoothAdapter.stopLeScan(mLeScanCallback);</span>
        <span style="font-family:DejaVu Sans Mono,monospace;">}</span>
        <span style="font-family:DejaVu Sans Mono,monospace;">...</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">}</span>
<span style="font-family:DejaVu Sans Mono,monospace;">...</span>
<span style="font-family:DejaVu Sans Mono,monospace;">}</span>



如果需要查找特定类型的LE设备,需要使用startLeScan(UUID[],BluetoothAdapter.LeScanCallback()),提供一个你的设备支持的服务的UUID数组。


LeScanCallback的实现:


<span style="font-family:DejaVu Sans Mono,monospace;">private LeDeviceListAdapter mLeDeviceListAdapter;</span>
<span style="font-family:DejaVu Sans Mono,monospace;">...</span>
<span style="font-family:DejaVu Sans Mono,monospace;">// Device scan callback.</span>
<span style="font-family:DejaVu Sans Mono,monospace;">private BluetoothAdapter.LeScanCallback mLeScanCallback =</span>
        <span style="font-family:DejaVu Sans Mono,monospace;">new BluetoothAdapter.LeScanCallback() {</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">@Override</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">public void onLeScan(final BluetoothDevice device, int rssi,</span>
            <span style="font-family:DejaVu Sans Mono,monospace;">byte[] scanRecord) {</span>
        <span style="font-family:DejaVu Sans Mono,monospace;">runOnUiThread(new Runnable() {</span>
           <span style="font-family:DejaVu Sans Mono,monospace;">@Override</span>
           <span style="font-family:DejaVu Sans Mono,monospace;">public void run() {</span>
               <span style="font-family:DejaVu Sans Mono,monospace;">mLeDeviceListAdapter.addDevice(device);</span>
               <span style="font-family:DejaVu Sans Mono,monospace;">mLeDeviceListAdapter.notifyDataSetChanged();</span>
           <span style="font-family:DejaVu Sans Mono,monospace;">}</span>
       <span style="font-family:DejaVu Sans Mono,monospace;">});</span>
   <span style="font-family:DejaVu Sans Mono,monospace;">}</span>
<span style="font-family:DejaVu Sans Mono,monospace;">};</span>


注意:要么搜索经典蓝牙,要么搜索BLE,两者不能同时搜索。


连接GATTserver

使用connectGatt连接到BLE设备的GATT server,

<span style="font-family:DejaVu Sans Mono,monospace;">mBluetoothGatt = device.connectGatt(this, false, mGattCallback);</span>



将会返回一个BluetoothGatt实例,通过这个实例可以进行Gattclient的各种操作。调用者(androidapp)是GattclientGattCallback用来提供结果给客户端。


读取BLE的属性

如果androidapp已经连接了Gatt server并且发现了服务,就能够进行属性的读写了。



收取Gatt的通知


通常BLEapp需要被通知,如果BLE设备的特性发生了改变。

使用setCharacteristicNotification方法为一个特性设置通知:

<span style="font-family:DejaVu Sans Mono,monospace;">private BluetoothGatt mBluetoothGatt;</span>
<span style="font-family:DejaVu Sans Mono,monospace;">BluetoothGattCharacteristic characteristic;</span>
<span style="font-family:DejaVu Sans Mono,monospace;">boolean enabled;</span>
<span style="font-family:DejaVu Sans Mono,monospace;">...</span>
<span style="font-family:DejaVu Sans Mono,monospace;">mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);</span>
<span style="font-family:DejaVu Sans Mono,monospace;">...</span>
<span style="font-family:DejaVu Sans Mono,monospace;">BluetoothGattDescriptor descriptor = characteristic.getDescriptor(</span>
        <span style="font-family:DejaVu Sans Mono,monospace;">UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));</span>
<span style="font-family:DejaVu Sans Mono,monospace;">descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);</span>
<span style="font-family:DejaVu Sans Mono,monospace;">mBluetoothGatt.writeDescriptor(descriptor);</span>


一旦一个特性被设置为通知可用,远端设备的特性发生改变就会触发onCharacteristicChanged

回调。

<span style="font-family:DejaVu Sans Mono,monospace;">@Override</span>
<span style="font-family:DejaVu Sans Mono,monospace;">// Characteristic notification</span>
<span style="font-family:DejaVu Sans Mono,monospace;">public void onCharacteristicChanged(BluetoothGatt gatt,</span>
        <span style="font-family:DejaVu Sans Mono,monospace;">BluetoothGattCharacteristic characteristic) {</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);</span>
<span style="font-family:DejaVu Sans Mono,monospace;">}</span>


关闭clientapp

结束和BLE设备的通讯后,需要释放资源:

<span style="font-family:DejaVu Sans Mono,monospace;">public void close() {</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">if (mBluetoothGatt == null) {</span>
        <span style="font-family:DejaVu Sans Mono,monospace;">return;</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">}</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">mBluetoothGatt.close();</span>
    <span style="font-family:DejaVu Sans Mono,monospace;">mBluetoothGatt = null;</span>
<span style="font-family:DejaVu Sans Mono,monospace;">}</span>

 

 

 

Android4.3 规范了BLE的API,但是直到目前的4.4,还有些功能不完善。

在BLE协议中,有两个角色,周边(Periphery)和中央(Central);周边是数据提供者,中央是数据使用/处理者;在iOS SDK里面,可以把一个iOS设备作为一个周边,也可以作为一个中央;但是在Android SDK里面,直到目前最新的Android4.4.2,Android手机只能作为中央来使用和处理数据;那数据从哪儿来?从BLE设备来,现在的很多可穿戴设备都是用BLE来提供数据的。

一个中央可以同时连接多个周边,但是一个周边某一时刻只能连接一个中央。

大概了解了概念后,看看Android BLE SDK的四个关键类(class):

a) BluetoothGattServer作为周边来提供数据;BluetoothGattServerCallback返回周边的状态。

b) BluetoothGatt作为中央来使用和处理数据;BluetoothGattCallback返回中央的状态和周边提供的数据。

因为我们讨论的是Android的BLE SDK,下面所有的BluetoothGattServer代表周边,BluetoothGatt代表中央。

一.创建一个周边(虽然目前周边API在Android手机上不工作,但还是看看)

a)先看看周边用到的class,蓝色椭圆

\

b)说明:

每一个周边BluetoothGattServer,包含多个服务Service,每一个Service包含多个特征Characteristic。

1.new一个特征:character = new BluetoothGattCharacteristic(
UUID.fromString(characteristicUUID),
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ);

2.new一个服务:service = new BluetoothGattService(UUID.fromString(serviceUUID),
BluetoothGattService.SERVICE_TYPE_PRIMARY);

3.把特征添加到服务:service.addCharacteristic(character);

4.获取BluetoothManager:manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

5.获取/打开周边:BluetoothGattServer server = manager.openGattServer(this,
new BluetoothGattServerCallback(){...});

6.把service添加到周边:server.addService(service);

7.开始广播service:Google还没有广播Service的API,等吧!!!!!所以目前我们还不能让一个Android手机作为周边来提供数据。


二.创建一个中央(这次不会让你失望,可以成功创建并且连接到周边的)

a)先看看中央用到的class,蓝色椭圆

加载中...下载地址:http://download.csdn.net/detail/jimoduwu/7072515


Android BLE 蓝牙低功耗教程,中央和周边的实现

Android4.3 规范了BLE的API,但是直到目前的4.4,还有些功能不完善。

在BLE协议中,有两个角色,周边(Periphery)和中央(Central);周边是数据提供者,中央是数据使用/处理者;在iOS SDK里面,可以把一个iOS设备作为一个周边,也可以作为一个中央;但是在Android SDK里面,直到目前最新的Android4.4.2,Android手机只能作为中央来使用和处理数据;那数据从哪儿来?从BLE设备来,现在的很多可穿戴设备都是用BLE来提供数据的。

一个中央可以同时连接多个周边,但是一个周边某一时刻只能连接一个中央。

大概了解了概念后,看看Android BLE SDK的四个关键类(class):

a) BluetoothGattServer作为周边来提供数据;BluetoothGattServerCallback返回周边的状态。

b) BluetoothGatt作为中央来使用和处理数据;BluetoothGattCallback返回中央的状态和周边提供的数据。

因为我们讨论的是Android的BLE SDK,下面所有的BluetoothGattServer代表周边,BluetoothGatt代表中央。

          

一.创建一个周边(虽然目前周边API在Android手机上不工作,但还是看看)

 a)先看看周边用到的class,蓝色椭圆


b)说明:

每一个周边BluetoothGattServer,包含多个服务Service,每一个Service包含多个特征Characteristic。

1.new一个特征:character = new BluetoothGattCharacteristic(
UUID.fromString(characteristicUUID),
BluetoothGattCharacteristic.PROPERTY_NOTIFY,
BluetoothGattCharacteristic.PERMISSION_READ);

2.new一个服务:service = new BluetoothGattService(UUID.fromString(serviceUUID),
BluetoothGattService.SERVICE_TYPE_PRIMARY);

3.把特征添加到服务:service.addCharacteristic(character);

4.获取BluetoothManager:manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

5.获取/打开周边:BluetoothGattServer server = manager.openGattServer(this,
new BluetoothGattServerCallback(){...}); 

6.把service添加到周边:server.addService(service);

7.开始广播service:Google还没有广播Service的API,等吧!!!!!所以目前我们还不能让一个Android手机作为周边来提供数据。


二.创建一个中央(这次不会让你失望,可以成功创建并且连接到周边的)

a)先看看中央用到的class,蓝色椭圆



b)说明:

为了拿到中央BluetoothGatt,可要爬山涉水十八弯:

1.先拿到BluetoothManager:bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

2.再拿到BluetoothAdapt:btAdapter = bluetoothManager.getAdapter();

3.开始扫描:btAdapter.startLeScan( BluetoothAdapter.LeScanCallback);

4.从LeScanCallback中得到BluetoothDevice:public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {.....}

5.用BluetoothDevice得到BluetoothGatt:gatt = device.connectGatt(this, true, gattCallback);

终于拿到中央BluetoothGatt了,它有一堆方法(查API吧),调用这些方法,你就可以通过BluetoothGattCallback和周边BluetoothGattServer交互了。


三.吐槽:

BluetoothAdapter.LeScanCallback是接口,但是BluetoothGattServerCallback和BluetoothGattCallback是抽象类,这两个抽象类让人很不爽,不知道google为什么要把他们搞成抽象类,完全可以搞成接口的嘛,或者又有抽象类又有接口也行啊,就像Runable和Thread一样多好。这两个抽象类对于有代码洁癖的人简直就是一种折磨,在方法参数里面new,还要实现父类方法,是在受不了。


Demo工程下载地址:http://download.csdn.net/detail/jimoduwu/7072515


 


  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值