Android低功耗蓝牙(BLE)使用详解
与普通蓝牙相比,低功耗蓝牙显著降低了能量消耗,允许Android应用程序与具有更严格电源要求的BLE设备进行通信,如接近传感器、心率传感器等低功耗设备。
声明蓝牙权限
和使用普通蓝牙一样,在使用低功耗蓝牙时也需要在AndroidManifest
声明蓝牙权限,声明蓝牙权限的代码如下
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
如果想让你的App只适用于BLE设备,可以在AndroidManifest
中继续添加以下代码
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
如果想让你的App适用于不支持BLE的设备,只需要将required="true"
改为required="false"
然后在代码中通过以下方法来判断设备是否支持BLE,
private void checkIsSupportBLE() {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
}
注:
LE信标往往与位置有关,如果想要通过``BluetoothLeScanner
方法来获取正确的扫描结果,需要在
AndroidManifest中声明位置权限,声明位置权限可以使用
ACCESS_COARSE_LOCATION或则
ACCESS_FINE_LOCATION` ,如过不声明位置权限,将不会返回蓝牙的扫描结果。
开启BLE
开启BLE只需要以下两步
-
在Android系统中只有一个
BluetoothAdapter
,可以通过以下方法来获取private void obtainBluetoothAdapter() {
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
}
开启蓝牙。
通过
isEnabled()
可以判断是否已经开启BLE,如果没有开启则可以通过以下方法来开启
//注册广播接受者
private void initReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mReceiver, filter);
}
//新建监听蓝牙状态变化的广播
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
BluetoothAdapter.ERROR);
switch (state) {
case BluetoothAdapter.STATE_OFF:
mBluetoothState.setText("Bluetooth off");
break;
case BluetoothAdapter.STATE_TURNING_OFF:
mBluetoothState.setText("Turning Bluetooth off...");
break;
case BluetoothAdapter.STATE_ON:
mBluetoothState.setText("Bluetooth on");
break;
case BluetoothAdapter.STATE_TURNING_ON:
mBluetoothState.setText("Turning Bluetooth on...");
break;
}
}
}
};
此广播包含额外字段
EXTRA_STATE
和EXTRA_PREVIOUS_STATE
,二者分别包含新的和旧的蓝牙状态。 这些额外字段可能的值包括STATE_TURNING_ON
、STATE_ON
、STATE_TURNING_OFF
和STATE_OFF
。侦听此广播适用于检测在您的应用运行期间对蓝牙状态所做的更改。
扫描BLE设备
扫描蓝牙设备可以通过 startLeScan(BluetoothAdapter.LeScanCallback)
和startLeScan(UUID[], BluetoothAdapter.LeScanCallback)
方法,这两种扫描BLE设备的区别如下。
startLeScan(BluetoothAdapter.LeScanCallback)
方法扫描的是周围所有的BLE设备。startLeScan(UUID[], BluetoothAdapter.LeScanCallback)
只扫描和UUID相匹配的设备。
可以发现无论通过哪种方式扫描蓝牙都必须要实现LeScanCallback
回调方法,此方法是用来获取蓝牙扫描结果。
通过以上两种方式实现扫描BLE设备的代码如下:
通过
startLeScan(BluetoothAdapter.LeScanCallback)
方法扫描蓝牙的代码如下//扫描BLE设备
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);
}
} //扫描结果回调
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();
}
});
}
};通过
startLeScan(UUID[], BluetoothAdapter.LeScanCallback)
方法扫描蓝牙的代码如下private void scanLeDeviceByUUID() {
mBluetoothAdapter.startLeScan(new UUID[]{RX_SERVICE_UUID}, mLeScanCallback);
}再次声明:
LE信标往往与位置有关,如果想要通过
BluetoothLeScanner
方法来获取正确的扫描结果,需要在AndroidManifest
中声明位置权限,声明位置权限可以使用ACCESS_COARSE_LOCATION
或则ACCESS_FINE_LOCATION
,如过不声明位置权限,将不会返回蓝牙的扫描结果。
连接BLE设备
要进行BLE设备之间的通讯,首先应该进行设备之间的连接,可以通过device.connectGatt (Context context,boolean autoConnect, BluetoothGattCallback callback)
方法来连接设备。
autoConnect
是设置当BLE设备可用时是否自动进行连接。device
就是通过扫描BLE设备获得的。callback
则是连接指定设备后的回掉,可以在回掉中知道是否建立连接、连接断开、以及获取设备之间传输的数据。
以下是BluetoothGattCallback
类中具体的方法
下面我会介绍几个比较常用的方法:
onConnectionStateChange
此方法的作用是可以获得设备连接的状态,如“成功连接”、“断开连接”。onServicesDiscovered
当远程设备的服务,特性和描述符列表已更新时(即发现新服务),调用此方法。onCharacteristicChanged
远程特征变化会调用此方法,即BLE设备的状态发生了变化会调用此方法。
onCharacteristicChanged
方法就是相当于BLE设备对你操作的回应,如打开BLE设备成功等,然后在此方法回掉之后,便可以继续下一步操作了。
操作BLE设备
在设备连接之后,就可以向BLE设备发送命令来操作BLE设备了,向BLE写数据的代码如下
public boolean writeByteToBleDevice(byte[] data) {
BluetoothGattService mBluetoothGattService = mBluetoothGatt.getService(RX_SERVICE_UUID);
if (mBluetoothGattService == null) {
return false;
}
BluetoothGattCharacteristic characteristic = mBluetoothGattService.getCharacteristic(RX_SERVICE_UUID);
if (characteristic == null) {
return false;
}
boolean b = characteristic.setValue(data);
return b && mBluetoothGatt.writeCharacteristic(characteristic);
}
在向BLE设备发送数据之后,就可以在onCharacteristicChanged
方法中获得BLE设备的状态了。
项目结构
项目代码结构图截图
结束语
这篇文章拖了这么久,总算写完了,本来打算在上一篇蓝牙文章写完后就写这篇,结果中间公司忙着上线新的项目,加班加点将近一个月,就没时间写这篇文章了,在项目上线之后就立马开始写这篇文章,希望这篇文章能帮到想要学习蓝牙的朋友。
Android低功耗蓝牙(BLE)使用详解
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
Android低功耗蓝牙(BLE)使用详解的更多相关文章
- 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发具体解释
转载请注明来源: http://blog.csdn.net/kjunchen/article/details/50909410 使用BleLib的轻松搞定Android低功耗蓝牙Ble 4.0开发具体 ...
- Android低功耗蓝牙(BLE)开发的一点感受
最近一段时间,因为产品的需要我做了一个基于低功耗蓝牙设备的Android应用,其中碰到了一些困难,使我深深体会到Android开发的难处:不同品牌,不同型号和不同版本之间的差异使得Android应用适 ...
- Android 低功耗蓝牙BLE 开发注意事项
基本概念和问题 1.蓝牙设计范式? 当手机通过扫描低功耗蓝牙设备并连接上后,手机与蓝牙设备构成了客户端-服务端架构.手机通过连接蓝牙设备,可以读取蓝牙设备上的信息.手机就是客户端,蓝牙设备是服务端. ...
- Android低功耗蓝牙(蓝牙4.0)——BLE开发(上)
段时间,公司项目用到了手机APP和蓝牙设备的通讯开发,这里也正好对低功耗蓝牙(蓝牙4.0及以后标准)的开发,做一个总结. 蓝牙技术联盟在2010年6月30号公布了蓝牙4.0标准,4.0标准在蓝牙3.0 ...
- 深入浅出讲解低功耗蓝牙(BLE)协议栈
详解BLE连接建立过程https://www.cnblogs.com/iini/p/8972635.html 详解BLE 空中包格式—兼BLE Link layer协议解析https://www.cn ...
- 【转】Android低功耗蓝牙应用开发获取的服务UUID
原文网址:http://blog.csdn.net/zhangjs0322/article/details/39048939 Android低功耗蓝牙应用程序开始时获取到的蓝牙血压计所有服务的UUID ...
- 低功耗蓝牙BLE外围模式(peripheral)-使用BLE作为服务端
低功耗蓝牙BLE外围模式(peripheral)-使用BLE作为服务端 Android对外模模式(peripheral)的支持 从Android5.0开始才支持 关键术语和概念 以下是关键BLE术语和 ...
- Android高效率编码-第三方SDK详解系列(一)——百度地图,绘制,覆盖物,导航,定位,细腻分解!
Android高效率编码-第三方SDK详解系列(一)--百度地图,绘制,覆盖物,导航,定位,细腻分解! 这是一个系列,但是我也不确定具体会更新多少期,最近很忙,主要还是效率的问题,所以一些有效的东西还 ...
- Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)
Android XML shape 标签使用详解 一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...
随机推荐
- 解决PHPExcel长数字串显示为科学计数
在excel中如果在一个默认的格中输入或复制超长数字字符串,它会显示为科学计算法,例如身份证号码,解决方法是把表格设置文本格式或在输入前加一个单引号. 使用PHPExcel来生成excel,也会遇到同 ...
- 【BZOJ 1119】 1119: [POI2009]SLO (置换)
1119: [POI2009]SLO Description 对于一个1-N的排列(ai),每次你可以交换两个数ax与ay(x<>y),代价为W(ax)+W(ay) 若干次交换的代价为每次 ...
- 机房重构包图(从三层+实体到三层+实体+外观+工厂+接口+SQLHelper)
刚刚开始接触三层的时候,我只做了两个登录小窗体的例子.画了简单的包图,可以说,为后面机房重构留下了大量的工作(因为三层理解没有深度,也没有理解出自己的东西).不过,欠下的总要还的.在做机房重构的时候, ...
- Codeforces 741B Arpa's weak amphitheater and Mehrdad's valuable Hoses
[题目链接] http://codeforces.com/problemset/problem/741/B [题目大意] 给出一张图,所有连通块构成分组,每个点有价值和代价, 要么选择整个连通块,要么 ...
- 【贪心】hdu5969 最大的位或
对于右端点r和左端点l,考虑他们的二进制位从高到低,直到第一位不同的为止. 更高的都取成相同的,更低的都取成1. 比如 101011110001 101011101001 101011111111 # ...
- httpWebRequest 文件下载
服务版本: go file system ssdb github: https://github.com/dtxlink/gfs 上一篇: 一个 go 文件服务器 ssdb 通过 httpWebReq ...
- String.format("%0"+length+"d", arr)中的%0和"d"分别代表什么
public static void main(String[] args) { int a = 8; String s = String.format("%04d", a); S ...
- 区块链 -- Merkle Tree
我们地球上大部分人应该连它的名字都没有听过,而且说实话它也是个比较传统的概念了.Merkle Tree 是由计算机科学家 Ralph Merkle 在很多年前提出的,并以他本人的名字来命名.不过,Me ...
- LATEX中优化问题如何排列Max——s.t.格式
做优化的同学可能会碰到排列形如 max ******* s.t. ***** = * ***** > *** ... 的格式 既要要求 max 和 s ...
- linux下编译运行C程序
GCC是Linux操作系统下一个非常重要的源代码编译工具,有着许多重要的选项,支持许多不同语言的编译,如C.C++.Ada.Fortran.Objective.Perl.Python.Ruby以及Ja ...