最近项目中使用到蓝牙打印机,通过蓝牙连接蓝牙打印机进行打印功能。在此对蓝牙知识进行归纳输出一波,达到巩固之效果。
蓝牙开发《基础篇一》
蓝牙开发《基础篇二》
BLE 蓝牙开发
英文: Bluetooth Low Energy.
版本要求:Android 18 之前 Android4.3版本以上才支持
官方文档:Bluetooth Low Energy
用处
可用于 Android 设备与智能设备间进行蓝牙通讯。
与经典的蓝牙对比
BLE 是低功耗型的,专门适用于 Android 设备与那些对电源有显著要求的 ble 设备,例如一些传感器之类的。
基本概念
-
Generic Attribute Profile (GATT)
-
Attribute Protocol (ATT) 属性协议,ATT 是经过优化了,可运行在 BLE 设备上,每一个属性都会有一个有一个 UUID(128bit) 保证唯一性。通过 ATT 传输的属性被格式为为 Characteristic 和 service
-
Characteristic 包含一个值 value 和 0-n 个 descriptor ,该 descriptor 是用于描述 value 。
-
Descriptor 被用于描述特征值的,可以指定一个描述,一个特征值的范围,或者特征值的度量单位
-
service 特征值的集合。
角色和职责
在 Android 设备和 BLE 设备进行交互时的角色和职责
角色:
-
中央角色 Central
-
外设角色 peripheral
两个相同角色的设备是不能进行相互通讯的
client
接收数据端
运行 android 程序的一端就是 GATT client
server
发送数据端
GATT server 端(BLE设备)
也可以让手机设备作为 GATT server 端
权限设置
<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"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
注意:android:required="true"当你想将app必须运行在支持BLE的设备,否则应该设置为false
当 android:required="false" 时,表示应用可以运行在非 BLE 设备上,可以通过相关的代码进行检测。
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
BLE 设置-准备工作
-
检测设备是否支持 BLE 特性
必须在 manifest 的 android:required="false"
-
如果支持 BLE 但是没开启,那么就要通过 intent 的方式开启
-
获取 BluetoothAdapter
private BluetoothAdapter mBluetoothAdapter;
...
// Initializes Bluetooth adapter.
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
- 检测蓝牙是否可用(前提支持BLE)
if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
查找 BLE 设备
通过 BluetoothAdapter.startLeScan 方法进行扫描,并且扫描结果会回调到 BluetoothAdapter.LeScanCallback 中
BluetoothAdapter.startLeScan(BluetoothAdapter.LeScanCallback )
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);
}
...
}
...
}
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();
}
});
} };
注意:
-
当扫描到指定的设备时应该停止扫描。
-
因为 startLeScan 是比较耗电的一个过程,需要设置一个扫描的时间限制。
-
不能同时扫描 BLE 和 经典蓝牙设备。
连接 GATT Server
由 GATT client 去调用 connectGatt 方法进行和 GATT Server 进行连接。
-
this 表示上下文
-
false 表示是否自动连接
-
mGattCallback 用于传输结果给客户端,例如连接的状态,客户端的一些操作
BluetoothGatt bluetoothGatt = device.connectGatt(this, false, mGattCallback); mGattCallback public void onConnectionStateChange(BluetoothGatt gatt, int status,int newState) //远程servier,characteristics,descriptor有更新时 public void onServicesDiscovered(BluetoothGatt gatt, int status) //通知一个特征值读的结果 public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,int status) // public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status)
总结
开发中遇到的问题
-
c语言与java语言出现数据的大小端问题。
-
数据超过20字节需要分包发送,20个字节是有head和data组成的。
-
每一子包的发送间隔在20ms。
网友评论