android4.3 nei內置了ble併爲上層app提供相應的接口來使用BLE功能。html
BLE主要涉及的協議及術語:android
GenericAttribute Profile (GATT)數組
BLE上層的協議都是基於GATT,它是一個通用的規範,經過BLE鏈接發送/接收屬性值。服務器
bluetoothSIG定義了不少的ble協議。app
AttributeProtocol (ATT)ide
GATT是創建在ATT之上。也被稱爲GATT/ATT。post
ATT運行在ble設備上,因此被優化,儘量的佔用較少的字節。優化
每個屬性被指定一個UUID,經過ATT傳輸的屬性被格式化位特性(characteristics)或服務(services)。ui
Characteristicthis
一個特性包含一個單一的值和0-n個描述符(Descriptor)來描述這個特性值。一個特性能夠被看做一個類型。
Descriptor
描述符被定義爲屬性,這些屬性用來描述特性的值。
例如:規定特性值的取值範圍,特性值的單位等
Service
服務是一組特性的集合。例如:「心率檢測」服務包含「心速測量」的特性。
角色和職責
中心與外圍:被應用於BLE鏈接自己,中心角色設備掃描/尋找廣播,外圍設備角色發出廣播。
GATTserver vs. GATT client:
這個決定了兩個設備在創建鏈接以後如何交互。
android手機和BLE設備的區別:手機支持中心角色(centralrole),BLE設備支持peripheralrole。
一旦創建鏈接,他們就開始相互傳輸gatt數據,根據傳輸的數據的種類其中的一個可能做爲服務器。
若是BLE設備想報告數據給手機,它可能讓BLE設備的傳感器做爲服務器。若是BLE設備準備接收來自手機的數據,手機的傳感器就做爲服務端。
以上例子說明:androidapp 是GATT client,GATTclient 從GATT server 獲取數據。也能夠設計android app 做爲GATTserver。
BLE權限:
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> |
若是想把app提供給不支持BLE的設備須要設置android:required="fasle",而後在運行時進行判斷:
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); finish(); } |
設置BLE
1:獲取BluetoothAdapter
BluetoothAdapter是全部藍牙功能所必需的,整個系統只有一個BluetoothAdapter,獲取BluetoothAdapter以後就能夠進行各類藍牙的操做了。
// Initializes Bluetooth adapter. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); |
2:啓動藍牙
經過isEnabled()判斷是否啓動,若是沒有啓動,經過下面的方式啓動:
private BluetoothAdapter mBluetoothAdapter; ... // Ensures Bluetooth is available on the device and it is enabled. If not, // displays a dialog requesting user permission to enable Bluetooth. if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } |
3:查找BLE設備
經過startLeScan查找LE設備,並實現LeScanCallback做爲參數。
注意事項:1:一旦找到所查找的設備,當即中止掃描
2:設置掃描超時,避免循環掃描。
public class DeviceScanActivity extends ListActivity { private BluetoothAdapter mBluetoothAdapter; private boolean mScanning; private Handler mHandler; // Stops scanning after 10 seconds. private static final long SCAN_PERIOD = 10000; ... private void scanLeDevice(final boolean enable) { if (enable) { // Stops scanning after a pre-defined scan period. mHandler.postDelayed(new Runnable() { @Override public void run() { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } }, SCAN_PERIOD); mScanning = true; mBluetoothAdapter.startLeScan(mLeScanCallback); } else { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } ... } ... } |
若是須要查找特定類型的LE設備,須要使用startLeScan(UUID[],BluetoothAdapter.LeScanCallback()),提供一個你的設備支持的服務的UUID數組。
LeScanCallback
的實現:
private LeDeviceListAdapter mLeDeviceListAdapter; ... // Device scan callback. private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { runOnUiThread(new Runnable() { @Override public void run() { mLeDeviceListAdapter.addDevice(device); mLeDeviceListAdapter.notifyDataSetChanged(); } }); } }; |
注意:要麼搜索經典藍牙,要麼搜索BLE,二者不能同時搜索。
鏈接GATTserver
使用connectGatt鏈接到BLE設備的GATT server,
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
|
將會返回一個BluetoothGatt實例,經過這個實例能夠進行Gattclient的各類操做。調用者(androidapp)是Gattclient。GattCallback用來提供結果給客戶端。
讀取BLE的屬性
若是androidapp已經鏈接了Gatt server而且發現了服務,就可以進行屬性的讀寫了。
收取Gatt的通知
一般BLEapp須要被通知,若是BLE設備的特性發生了改變。
使用setCharacteristicNotification方法爲一個特性設置通知:
private BluetoothGatt mBluetoothGatt; BluetoothGattCharacteristic characteristic; boolean enabled; ... mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); ... BluetoothGattDescriptor descriptor = characteristic.getDescriptor( UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG)); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); |
一旦一個特性被設置爲通知可用,遠端設備的特性發生改變就會觸發onCharacteristicChanged
回調。
@Override // Characteristic notification public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } |
關閉clientapp
結束和BLE設備的通信後,須要釋放資源:
public void close() { if (mBluetoothGatt == null) { return; } mBluetoothGatt.close(); mBluetoothGatt = null; } |