android BLE4.0 流程图
2016-05-22 13:51
399 查看
BLE蓝牙在android上连接,底层实现读取的详细执行过程:
1、扫描:
使用BluetoothAdapter.startLeScan来扫描低功耗蓝牙设备,获取设备对象device,通过device.address,device.name获取设备名称和mac地址,通过mac地址分配每个设备唯一名称,例:体温计1,体温计2...。
在扫描到设备的回调函数中获得所有device对象,并使用BluetoothAdapter.stopLeScan停止扫描。
2、连接和读写数据:
使用BluetoothDevice.connectGatt来获取到BluetoothGatt对象;
执行BluetoothGatt.discoverServices,这个方法是异步操作,在回调函数onServicesDiscovered中得到status,通过判断status是否等于BluetoothGatt.GATT_SUCCESS来判断查找Service是否成功;
如果成功了,则通过BluetoothGatt.getService来获取BluetoothGattService;
接着通过BluetoothGattService.getCharacteristic获取BluetoothGattCharacteristic;
然后通过BluetoothGattCharacteristic.getValue获取体温数据。
主要使用BluetoothLeService对上图流程进行控制。BluetoothLeService封装了androidframework
层bluetooth的相关对象和操作方法、回调方法包括:
android.bluetooth.BluetoothAdapter;
android.bluetooth.BluetoothDevice;
android.bluetooth.BluetoothGatt;
android.bluetooth.BluetoothGattCallback;
android.bluetooth.BluetoothGattCharacteristic;
android.bluetooth.BluetoothGattService;
android.bluetooth.BluetoothManager;
android.bluetooth.BluetoothProfile;
initialize();初始化
disconnect();断开与远程设备的GATT连接
close();关闭关闭GATT
readCharacteristic();读取指定的characteristic
readDeviceData();读取设备信息
connect();连接设备
getCharacteristic();获取BluetoothGattCharacteristic对象
SendReadOrder();发送读数据指令
getSupportedGattServices();获取所有服务
BluetoothLeService采用与显示层bind,unbind的方式,在后台保持运行,并提供与前台交互的android组件BroadcastReceiver传递消息。
1、扫描:
使用BluetoothAdapter.startLeScan来扫描低功耗蓝牙设备,获取设备对象device,通过device.address,device.name获取设备名称和mac地址,通过mac地址分配每个设备唯一名称,例:体温计1,体温计2...。
在扫描到设备的回调函数中获得所有device对象,并使用BluetoothAdapter.stopLeScan停止扫描。
2、连接和读写数据:
使用BluetoothDevice.connectGatt来获取到BluetoothGatt对象;
执行BluetoothGatt.discoverServices,这个方法是异步操作,在回调函数onServicesDiscovered中得到status,通过判断status是否等于BluetoothGatt.GATT_SUCCESS来判断查找Service是否成功;
如果成功了,则通过BluetoothGatt.getService来获取BluetoothGattService;
接着通过BluetoothGattService.getCharacteristic获取BluetoothGattCharacteristic;
然后通过BluetoothGattCharacteristic.getValue获取体温数据。
主要使用BluetoothLeService对上图流程进行控制。BluetoothLeService封装了androidframework
层bluetooth的相关对象和操作方法、回调方法包括:
android.bluetooth.BluetoothAdapter;
android.bluetooth.BluetoothDevice;
android.bluetooth.BluetoothGatt;
android.bluetooth.BluetoothGattCallback;
android.bluetooth.BluetoothGattCharacteristic;
android.bluetooth.BluetoothGattService;
android.bluetooth.BluetoothManager;
android.bluetooth.BluetoothProfile;
initialize();初始化
disconnect();断开与远程设备的GATT连接
close();关闭关闭GATT
readCharacteristic();读取指定的characteristic
readDeviceData();读取设备信息
connect();连接设备
getCharacteristic();获取BluetoothGattCharacteristic对象
SendReadOrder();发送读数据指令
getSupportedGattServices();获取所有服务
BluetoothLeService采用与显示层bind,unbind的方式,在后台保持运行,并提供与前台交互的android组件BroadcastReceiver传递消息。
/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mehow.mehowhealth.bluetooth; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.List; import java.util.UUID; import android.app.Service; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class BluetoothLeService extends Service implements BleManager{ private final static String TAG = BluetoothLeService.class.getSimpleName(); private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private String mBluetoothDeviceAddress; private BluetoothGatt mBluetoothGatt; private int order;// 表示发送的是什么读取命令 private BluetoothGattCharacteristic characteristic; private final IBinder mBinder = new LocalBinder(); private int mConnectionState = STATE_DISCONNECTED; private static final int STATE_DISCONNECTED = 0; private static final int STATE_CONNECTING = 1; private static final int STATE_CONNECTED = 2; // 广播标识 public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED"; public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED"; public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED"; public final static String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE"; public final static String EXTRA_DATA = "com.example.bluetooth.le.EXTRA_DATA"; public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID.fromString("00002a37-0000-1000-8000-00805f9b34fb"); public final static String CHANGE_PRODUCT_PARAMETER = "CHANGE_PRODUCT_PARAMETER"; /** * 判断BluetoothAdapter对象 * */ public boolean initialize() { if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { return false; } } mBluetoothAdapter = mBluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { return false; } return true; } /** * 断开与远程设备的GATT连接 */ public void disconnect() { if (mBluetoothAdapter == null || mBluetoothGatt == null) { return; } mBluetoothGatt.disconnect(); Log.i(TAG, "disconnect:--------2"+mBluetoothGatt); } /** * 关闭关闭GATT */ public void close() { if (mBluetoothGatt == null) { return; } mBluetoothGatt.close(); mBluetoothGatt = null; Log.i(TAG, "disconnect:--------2"+mBluetoothGatt); } /** * 读取指定的characteristic */ public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { return false; } this.characteristic = characteristic; return mBluetoothGatt.readCharacteristic(characteristic); } public interface onReadListener { public void ReadData(byte[] bys, int order); } // 供上层调用 public void getReadtData(onReadListener listener) { byte[] by = readDeviceData(); listener.ReadData(by, order); } // 读取设备信息 public byte[] readDeviceData() { byte[] data = null; if (characteristic == null) { return null; } if (UUID.fromString(Constant.SERVICEUUID).equals( characteristic.getUuid())) { int flag = characteristic.getProperties(); int format = -1; if ((flag & 0x01) != 0) { format = BluetoothGattCharacteristic.FORMAT_UINT16; } else { format = BluetoothGattCharacteristic.FORMAT_UINT8; } final int heartRate = characteristic.getIntValue(format, 1); } else { data = characteristic.getValue(); } return data; } /** * 连接设备 */ public boolean connect(final String address) { if (mBluetoothAdapter == null || address == null) { return false; } if (mBluetoothDeviceAddress != null&& address.equals(mBluetoothDeviceAddress)&& mBluetoothGatt != null) { if (mBluetoothGatt.connect()) { mConnectionState = STATE_CONNECTING; return true; } else { return false; } } final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); if (device == null) { return false; } mBluetoothGatt = device.connectGatt(this, false, back); Log.i("FH", "mBluetoothGatt:"+mBluetoothGatt); mBluetoothDeviceAddress = address; mConnectionState = STATE_CONNECTING; return true; } // 获取制定UUID的BluetoothGattCharacteristic对象 // 参数:service_uuid--BluetoothGattService的UUID;characteristic_uuid:BluetoothGattCharacteristic的UUID public BluetoothGattCharacteristic getCharacteristic(String service_uuid,String characteristic_uuid) { BluetoothGattService gService = mBluetoothGatt.getService(UUID .fromString(service_uuid)); if (gService == null) { return null; } BluetoothGattCharacteristic characteristic = gService .getCharacteristic(UUID.fromString(characteristic_uuid)); return characteristic; } // 发送读数据指令 // 参数:by--要发送的指令;characteristic---要发给具体的对象 public boolean SendReadOrder(byte[] by,BluetoothGattCharacteristic characteristic, int identifying) { if (by == null || characteristic == null) { return false; } order = identifying; boolean status = false; int storedLevel = characteristic.getWriteType(); Log.d(TAG, "storedLevel() - storedLevel=" + storedLevel); characteristic.setValue(by); characteristic .setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); status = mBluetoothGatt.writeCharacteristic(characteristic); Log.d(TAG, "writeLlsAlertLevel() - status=" + status); return status; } /** * 获取所有服务 */ public List<BluetoothGattService> getSupportedGattServices() { if (mBluetoothGatt == null) return null; return mBluetoothGatt.getServices(); } public class LocalBinder extends Binder { public BluetoothLeService getService() { return BluetoothLeService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } /** * BluetoothGatt回调函数 */ private final BluetoothGattCallback back = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) { String intentAction; if (newState == BluetoothProfile.STATE_CONNECTED) { intentAction = ACTION_GATT_CONNECTED; mConnectionState = STATE_CONNECTED; Log.i(TAG, "Connected to GATT server."); // Attempts to discover services after successful connection. Log.i(TAG, "Attempting to start service discovery:"+ mBluetoothGatt.discoverServices()); Log.i("FH", "mBluetoothGatt-------7897987987:"+mBluetoothGatt.getServices().size()); System.out.println("已经连接上设备"); broadcastUpdate(intentAction); Log.i(TAG, "Connected to GATT server."); // Attempts to discover services after successful connection. } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { intentAction = ACTION_GATT_DISCONNECTED; mConnectionState = STATE_DISCONNECTED; Log.i(TAG, "Disconnected from GATT server."); broadcastUpdate(intentAction); System.out.println("已经断开设备"); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { System.out.println("onServicesDiscovered------4623462462------------"); broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); Log.i("FH", "mBluetoothGatt:"+mBluetoothGatt.getServices().size()); } else { Log.w(TAG, "onServicesDiscovered received: " + status); } } @Override public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } Log.i(TAG, "characteristic----------1:"+characteristic); Log.i(TAG, "mBluetoothGatt----------1:"+mBluetoothGatt.getServices().size()); } @Override public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); Log.i(TAG, "characteristic----------2:"+characteristic); Log.i(TAG, "mBluetoothGatt----------2:"+mBluetoothGatt.getServices().size()); } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.d(TAG, "onCharacteristicWrite" + Arrays.toString(characteristic.getValue())); }; }; private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); sendBroadcast(intent); } /** * 发送广播 * * @param action * @param characteristic */ private void broadcastUpdate(final String action,final BluetoothGattCharacteristic characteristic) { final Intent intent = new Intent(action); // This is special handling for the Heart Rate Measurement profile. Data // parsing is // carried out as per profile specifications: // http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { int flag = characteristic.getProperties(); Log.d(TAG, flag + ""); int format = -1; if ((flag & 0x01) != 0) { format = BluetoothGattCharacteristic.FORMAT_UINT16; Log.d(TAG, "Heart rate format UINT16."); } else { format = BluetoothGattCharacteristic.FORMAT_UINT8; Log.d(TAG, "Heart rate format UINT8."); } final int heartRate = characteristic.getIntValue(format, 1); Log.d(TAG, String.format("Received heart rate: %d", heartRate)); intent.putExtra(EXTRA_DATA, String.valueOf(heartRate)); } else { final byte[] data = characteristic.getValue(); // --------------------------------- if (data != null && data.length > 0) { final StringBuilder stringBuilder = new StringBuilder(data.length); for (byte byteChar : data) { stringBuilder.append(String.format("%02X ", byteChar)); } // stringBuilder.append(String.valueOf(byteChar)); intent.putExtra(EXTRA_DATA, new String(data) + "\n"+ stringBuilder.toString()); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 设置日期格式 System.out.println(df.format(System.currentTimeMillis())+ "-----" + stringBuilder.toString()); intent.putExtra("byte", data); intent.putExtra("order", order); // ------------------------------------------------- } // For all other profiles, writes the data formatted in HEX. } sendBroadcast(intent); } /** * 解绑Service */ @Override public boolean onUnbind(Intent intent) { close(); return super.onUnbind(intent); } @Override public byte[] initReadOrder(int identifying, byte[] be) { byte[] by = null; switch (identifying) { case Constant.PRODUCT_PARAMETER: if (be != null) { by = new byte[7]; by[0] = 0x11; by[1] = 0x08; by[2] = 0x01; by[3] = 0x03; by[4] = be[0]; by[5] = be[1]; by[6] = be[2]; } break; case Constant.DATA: by = new byte[4]; by[0] = 0x11; by[1] = 0x02; by[2] = 0x08; by[3] = 0x00; break; case Constant.HISTORY_RECORD:// 历史记录 if (be != null) { by = new byte[6]; by[0] = Constant.SERIES_NUMBER[0]; by[1] = Constant.SERIES_NUMBER[1]; by[2] = Constant.SERIES_NUMBER[2]; by[3] = Constant.SERIES_NUMBER[3]; by[4] = be[0]; by[5] = be[1]; } break; case Constant.USER_INFO:// 写入用户信息 by = new byte[14]; by[0] = 0x11; by[1] = 0x04; by[2] = 0x08; by[3] = 0x0A; by[4] = Constant.SERIES_NUMBER[0]; by[5] = Constant.SERIES_NUMBER[1]; by[6] = Constant.SERIES_NUMBER[2]; by[7] = Constant.SERIES_NUMBER[3]; break; case Constant.USER_HISTORY_RECORD:// 读取用户信息,查询是否有历史记录 by = new byte[8]; by[0] = 0x11; by[1] = 0x03; by[2] = 0x08; by[3] = 0x04; by[4] = Constant.SERIES_NUMBER[0]; by[5] = Constant.SERIES_NUMBER[1]; by[6] = Constant.SERIES_NUMBER[2]; by[7] = Constant.SERIES_NUMBER[3]; break; default: break; } return by; } @Override public byte[] int2byte(int res) { byte[] targets = new byte[2]; targets[0] = (byte) ((res >> 8) & 0xff); targets[1] = (byte) (res & 0xff); return targets; } }
相关文章推荐
- android_简易画板_笔记
- Android Fragment 你应该知道的一切
- 一些关于android屏幕的小知识
- Android Studio系列教程与技巧目录
- Android四大组件(1.1)--Activity的生命周期
- Android之Tab类总结
- android 访问webservice问题
- Android Animation 遇到的一些问题
- 【Android】 TextView设置个别字体样式
- alipay--- Android 集成支付宝SDK实现快捷支付--详解
- Android系统自带样式(@android:style/)
- Android activitylifecyclecallbacks
- Android中的线程
- Android.mk添加第三方jar包
- Android 小贴士播报
- Android 开源项目浅读-------SwipeMenuListView-重写,八章,菜单响应
- android-activity启动模式
- android studio 预览问题 :java.lang.NoClassDefFoundError: com/android/util/PropertiesMap
- 自定义Android渐变式圆环滑动条
- Android,View设置margin