Android BLE最完整的工具类(扫描/连接/读写/通知设备),可以手机与设备进行通讯
来源:互联网 发布:php平台是干什么用呢? 编辑:程序博客网 时间:2024/04/30 23:34
这里只要是Android设备与BLE设备的通讯都可以共用,只需要该的就是uuid的值,还有就是ble设备提供商要出文档协议,看看是如何发命令跟接收命令的。
bleUtil工具中,有些地方我感觉还是要提示下
1、characterUUID1 、characterUUID2 、descriptorUUID 这三个是对应的收发命令的,跟找到要操作的BluetoothGattDescriptor(特性)。
在做这个项目的时候ble设备提供商给的文档中uuid,是短的,我实际我打印出来的是长的。其实短的那种是ios来的,而android就不一样咯。可以参考:Android与IOS的UUID的区别
2、sendWorkModel、sendStrength 这两个方法是用来发送命令的,传值都是byte[]数组;而接收命令的话通过receiveData方法进行解析得到的byte[]。这三个方法都是需要根据不同设备协议进行修改,这里只是为了案例展示。总的来说就是收发命令都是byte[]
一丶关键概念:
Generic Attribute Profile (GATT)
通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。
Attribute Protocol (ATT)
GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。
每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。
Characteristic
Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。
Descriptor
对Characteristic的描述,例如范围、计量单位等。
Service
Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,
它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement"的Characteristic。
二丶角色和职责:
二丶角色和职责:
Android设备与BLE设备交互有两组角色:
中心设备和外围设备(Central vs. peripheral);
GATT server vs. GATT client.
Central vs. peripheral:
中心设备和外围设备的概念针对的是BLE连接本身。
Central角色负责scan advertisement。而peripheral角色负责make advertisement。
GATT server vs. GATT client:
这两种角色取决于BLE连接成功后,两个设备间通信的方式。
举例说明:
现有一个活动追踪的BLE设备和一个支持BLE的Android设备。
Android设备支持Central角色,而BLE设备支持peripheral角色。
创建一个BLE连接需要这两个角色都存在,都仅支持Central角色或者都仅支持peripheral角色则无法建立连接。
当连接建立后,它们之间就需要传输GATT数据。
谁做server,谁做client,则取决于具体数据传输的情况。
例如,如果活动追踪的BLE设备需要向Android设备传输sensor数据,则活动追踪器自然成为了server端;
而如果活动追踪器需要从Android设备获取更新信息,则Android设备作为server端可能更合适。
三丶权限及feature:
三丶权限及feature:
和经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,
如果需要扫描设备或者操作蓝牙设置,则还需要BLUETOOTH_ADMIN权限:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature:
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
按时required为true时,则应用只能在支持BLE的Android设备上安装运行;
required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature
四丶通讯设备的主要步骤有:
设置权限--->打开蓝牙--->扫描设备--->连接设备--->读写数据+通知设备的状态改变--->断开设备
五丶BluetoothGatt的服务层次:
BluetoothGatt--->BluetoothGattService(服务)--->BluetoothGattCharacteristic(特征)--->BluetoothGattDescriptor(特性)
下面的就是重点啦!工具类,工具类,工具类好听的话说三遍
四丶通讯设备的主要步骤有:
设置权限--->打开蓝牙--->扫描设备--->连接设备--->读写数据+通知设备的状态改变--->断开设备
五丶BluetoothGatt的服务层次:
BluetoothGatt--->BluetoothGattService(服务)--->BluetoothGattCharacteristic(特征)--->BluetoothGattDescriptor(特性)
下面的就是重点啦!工具类,工具类,工具类好听的话说三遍
import android.annotation.TargetApi;import android.app.Activity;import android.bluetooth.BluetoothAdapter;import android.bluetooth.BluetoothDevice;import android.bluetooth.BluetoothGatt;import android.bluetooth.BluetoothGattCallback;import android.bluetooth.BluetoothGattCharacteristic;import android.bluetooth.BluetoothGattDescriptor;import android.bluetooth.BluetoothGattService;import android.bluetooth.BluetoothManager;import android.bluetooth.BluetoothProfile;import android.content.Context;import android.content.pm.PackageManager;import android.os.Build;import android.os.Handler;import android.util.Log;import android.widget.Toast;import java.util.ArrayList;import java.util.List;import java.util.UUID;/** * Created by shaolin on 6/17/16. */@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)public class BleUtil { private static final String TAG = "BleUtil"; private static final long SCAN_PERIOD = 10000; public static String characterUUID1 = "0000fff2-0000-1000-8000-00805f9b34fb";//APP发送命令 public static String characterUUID2 = "0000fff1-0000-1000-8000-00805f9b34fb";//BLE用于回复命令 private static String descriptorUUID = "00002902-0000-1000-8000-00805f9b34fb";//BLE设备特性的UUID public static byte[] workModel = {0x02, 0x01}; private Context mContext; private static BleUtil mInstance; //作为中央来使用和处理数据; private BluetoothGatt mGatt; private BluetoothManager manager; private BTUtilListener mListener; private BluetoothDevice mCurDevice; private BluetoothAdapter mBtAdapter; private List<BluetoothDevice> listDevice; private List<BluetoothGattService> serviceList;//服务 private List<BluetoothGattCharacteristic> characterList;//特征 private BluetoothGattService service; private BluetoothGattCharacteristic character1; private BluetoothGattCharacteristic character2; public static synchronized BleUtil getInstance() { if (mInstance == null) { mInstance = new BleUtil(); } return mInstance; } public void setContext(Context context) { mContext = context; init(); } public void init() { listDevice = new ArrayList<>(); if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { showToast("BLE不支持此设备!"); ((Activity) mContext).finish(); } manager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); //注:这里通过getSystemService获取BluetoothManager, //再通过BluetoothManager获取BluetoothAdapter。BluetoothManager在Android4.3以上支持(API level 18)。 if (manager != null) { mBtAdapter = manager.getAdapter(); } if (mBtAdapter == null || !mBtAdapter.isEnabled()) { mBtAdapter.enable(); /*Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); mContext.startActivity(enableBtIntent);*/ } } //扫描设备的回调 private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { ((Activity) mContext).runOnUiThread(new Runnable() { @Override public void run() { if (!listDevice.contains(device)) { //不重复添加 listDevice.add(device); mListener.onLeScanDevices(listDevice); Log.e(TAG, "device:" + device.toString()); } } }); } }; //扫描设备 public void scanLeDevice(final boolean enable) { if (enable) { Handler mHandler = new Handler(); mHandler.postDelayed(new Runnable() { @Override public void run() { stopScan(); Log.e(TAG, "run: stop"); } }, SCAN_PERIOD); startScan(); Log.e(TAG, "start"); } else { stopScan(); Log.e(TAG, "stop"); } } //开始扫描BLE设备 private void startScan() { mBtAdapter.startLeScan(mLeScanCallback); mListener.onLeScanStart(); } //停止扫描BLE设备 private void stopScan() { mBtAdapter.stopLeScan(mLeScanCallback); mListener.onLeScanStop(); } //返回中央的状态和周边提供的数据 private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { Log.e(TAG, "onConnectionStateChange"); switch (newState) { case BluetoothProfile.STATE_CONNECTED: Log.e(TAG, "STATE_CONNECTED"); mListener.onConnected(mCurDevice); gatt.discoverServices(); //搜索连接设备所支持的service break; case BluetoothProfile.STATE_DISCONNECTED: mListener.onDisConnected(mCurDevice); disConnGatt(); Log.e(TAG, "STATE_DISCONNECTED"); break; case BluetoothProfile.STATE_CONNECTING: mListener.onConnecting(mCurDevice); Log.e(TAG, "STATE_CONNECTING"); break; case BluetoothProfile.STATE_DISCONNECTING: mListener.onDisConnecting(mCurDevice); Log.e(TAG, "STATE_DISCONNECTING"); break; } super.onConnectionStateChange(gatt, status, newState); } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { Log.d(TAG, "onServicesDiscovered"); if (status == BluetoothGatt.GATT_SUCCESS) { serviceList = gatt.getServices(); for (int i = 0; i < serviceList.size(); i++) { BluetoothGattService theService = serviceList.get(i); Log.e(TAG, "ServiceName:" + theService.getUuid()); characterList = theService.getCharacteristics(); for (int j = 0; j < characterList.size(); j++) { String uuid = characterList.get(j).getUuid().toString(); Log.e(TAG, "---CharacterName:" + uuid); if (uuid.equals(characterUUID1)) { character1 = characterList.get(j); } else if (uuid.equals(characterUUID2)) { character2 = characterList.get(j); setNotification(); } } } } super.onServicesDiscovered(gatt, status); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.e(TAG, "onCharacteristicRead"); super.onCharacteristicRead(gatt, characteristic, status); } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.e(TAG, "onCharacteristicWrite"); super.onCharacteristicWrite(gatt, characteristic, status); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { Log.e(TAG, "onCharacteristicChanged");// 这里是可以监听到设备自身或者手机改变设备的一些数据修改h通知 receiveData(characteristic); super.onCharacteristicChanged(gatt, characteristic); } }; //获取设备指定的特征中的特性,其中对其进行监听, setCharacteristicNotification与上面的回调onCharacteristicChanged进行一一搭配 private void setNotification() { mGatt.setCharacteristicNotification(character2, true); BluetoothGattDescriptor descriptor = character2.getDescriptor(UUID.fromString(descriptorUUID)); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mGatt.writeDescriptor(descriptor); } //接收数据,对其进行处理 private void receiveData(BluetoothGattCharacteristic ch) { byte[] bytes = ch.getValue(); int cmd = bytes[0]; int agree = bytes[1]; switch (cmd) { case 1: mListener.onStrength(agree); Log.e(TAG, "手机通知BLE设备强度:" + agree); break; case 2: mListener.onModel(agree); Log.e(TAG, "工作模式:" + agree); break; case 3: mListener.onStrength(agree); Log.e(TAG, "设备自身通知改变强度:" + agree); break; } } //连接设备 public void connectLeDevice(int devicePos) { mBtAdapter.stopLeScan(mLeScanCallback); mCurDevice = listDevice.get(devicePos); checkConnGatt(); } //发送进入工作模式请求 public void sendWorkModel() { if (character1 != null) { character1.setValue(workModel); mGatt.writeCharacteristic(character1); } } //发送强度 public void sendStrength(int strength) { byte[] strengthModel = {0x01, (byte) strength}; if (character1 != null) { character1.setValue(strengthModel); mGatt.writeCharacteristic(character1); } } //检查设备是否连接了 private void checkConnGatt() { if (mGatt == null) { mGatt = mCurDevice.connectGatt(mContext, true, mGattCallback); mListener.onConnecting(mCurDevice); } else { mGatt.connect(); mGatt.discoverServices(); } } // 断开设备连接 private void disConnGatt() { if (mGatt != null) { mGatt.disconnect(); mGatt.close(); mGatt = null; listDevice = new ArrayList<>(); mListener.onLeScanDevices(listDevice); } } private void showToast(String message) { Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show(); } public void setBTUtilListener(BTUtilListener listener) { mListener = listener; } public interface BTUtilListener { void onLeScanStart(); // 扫描开始 void onLeScanStop(); // 扫描停止 void onLeScanDevices(List<BluetoothDevice> listDevice); //扫描得到的设备 void onConnected(BluetoothDevice mCurDevice); //设备的连接 void onDisConnected(BluetoothDevice mCurDevice); //设备断开连接 void onConnecting(BluetoothDevice mCurDevice); //设备连接中 void onDisConnecting(BluetoothDevice mCurDevice); //设备连接失败 void onStrength(int strength); //给设备设置强度 void onModel(int model); //设备模式 }}
参考:http://www.myext.cn/android/a_4699.html
重点: Android与IOS的UUID的区别
0 1
- Android BLE最完整的工具类(扫描/连接/读写/通知设备),可以手机与设备进行通讯
- Android BLE设备扫描
- Android开发蓝牙与ble设备的通讯
- android 手机与蓝牙设备的通讯
- Android BLE 中心设备与外设进行大数据的读写
- Android设备与USB设备的连接通讯
- android 蓝牙通讯实现手机蓝牙的开启,并扫描附近可见的蓝牙设备
- Android蓝牙4.0BLE与智能设备间的通讯全解析
- Android BLE低功耗蓝牙开发(下) BLE客户端(中央设备)与GATT服务的通讯
- Android手机与多个BLE设备通信
- Android手机与多个BLE设备通信
- Android/安卓开发之WIFI通讯(下)--与搜索到的设备进行通讯
- 微信小程序Ble设备连接与发送
- Android智能设备蓝牙连接(BLE)
- android app与蓝牙设备之间连接与通讯
- android ble : 一(蓝牙门禁的ble通讯完整流程)
- 安卓通讯之《蓝牙单片机通讯助手》②扫描设备、连接设备和双向通讯。
- S3连接ble设备的一个问题
- ~ 运算符的 小知识
- 最小公倍数与最大公约数的研究
- 读书笔记-java网络编程-5URL和URI-简述
- 我爱我家:我为什么选择AppCan?
- tableView侧边栏索引
- Android BLE最完整的工具类(扫描/连接/读写/通知设备),可以手机与设备进行通讯
- 弧形Dialog进度条
- 10007---关于Java并发编程的总结和思考
- 详解spring 每个jar的作用
- SparkSQL------初涉
- 将JSON转换成MAP的工具类
- Post请求传递参数时,最好在请求头加上item.ContentType = "application/x-www-form-urlencoded";
- 20160704
- Crossfilter总结