添加蓝牙权限
特性请求
值为true则指定设备必须带BLE才能安装该应用程序
值为false则不论设备是否带BLE都可以安装应用程序(但运行时必须判断设备是否支持该特性
判断设备是否支持BLE(如果特性请求指定为true,则不需要判断)
if(!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
}
获取本地蓝牙适配器(即本地的蓝牙功能模块)
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
后面一切关于蓝牙的内容都要从BluetoothAdapter开始
判断蓝牙是否开启以及请求启动蓝牙
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
//请求启动蓝牙
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
下面开始扫描设备
首先要实现以下接口:
android.bluetooth.BluetoothAdapter.LeScanCallback
我在这里通过Activity直接implements这个接口,所以在使用时直接传入this就可以了:
public void onLeScan(BluetoothDevice device, int rssi, byte[] arg2) {
// TODO Auto-generated method stub
final String name = device.getName();
final String addr = device.getAddress();
}
启动/停止扫描
private synchronized void startScan()
{
gapUtil.btAdapter.startLeScan(this);//传入扫描回调方法
handler.postDelayed(scanTimingTask, 10000); //10秒后取消扫描
}
private synchronized void stopScan()
{
gapUtil.btAdapter.stopLeScan(this);
handler.removeCallbacks(scanTimingTask);
}
//扫描超时任务
private Runnable scanTimingTask = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
isScaning = false;
stopScan();
}
};
因为扫描设备时是很耗电的,所以一定要设置扫描的时间(这是设置为10s)
扫描到设备后,会触发上面的扫描回调方法,可以在该方法中添加设备信息到列表中,也可直接发起链接,但是不要在这里更新UI,因为回调方法的调用不在UI线程中,如果需要更新UI,请使用handler.post()或者runOnUiThread();
实现设备的链接
先获取远程设备的引用,然后通过该引用发起链接。
BluetoothDevice btDevice = btAdapter.getRemoteDevice(addr);//远程设备
BluetoothGatt btGatt = btDevice.connectGatt(mContext, false, btCallback);//传入gatt回调方法
这里的connectGatt()方法第三个参数需要传入Gatt层的回调函数,为此我们要先实现该回调方法,但设备链接成功后,会触发该回调方法的onConnectionStateChange()方法:
BluetoothGattCallback btCallback = new BluetoothGattCallback() {
@Override
//当设备通过Notification发送数据过来时,回调该方法
public void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
// TODO Auto-generated method stub
super.onCharacteristicChanged(gatt, characteristic);
}
@Override
//链接状态改变时回调该方法
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
// TODO Auto-generated method stub
super.onConnectionStateChange(gatt, status, newState);
}
@Override
//发现service时回调该方法
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
// TODO Auto-generated method stub
super.onServicesDiscovered(gatt, status);
}
};
寻找Service
当设备建立链接成功后,可对设备进行Service搜索:
switch (newState)
{
case BluetoothGatt.STATE_CONNECTED:
BluetoothGatt. discoverServices();//执行该方法寻找Service,成功后,会触发onServicesDiscovered()被调用
break;
default:break;
}
获取Service列表
Service搜索完毕,会触发gatt回调方法的onServicesDiscovered()方法被调用,在这里我们可以获取设备的Service列表
BluetoothGatt.getServices()
获取指定Service下的Characteristic列表
BluetoothGattService.getCharateristics();
获取Characteristic的属性
BluetoothGattCharateristic.getProperties();
属性类型包括:
PROPERTY_INDICATE=0x20; //可接收Indication
PROPERTY_NOTIFY=0x10; //可接收Notification
PROPERTY_READ=0x02; //可读
PROPERTY_WRITE=0x08; //可写
PROPERTY_WRITE_NO_RESPONSE=0x04; //可无回应的写
PROPERTY_SIGN_WRITE=0x40; //认证可写(配对)
…
通过获取Characteristic的属性可以用来判断特征值是否可读?可写?可Notify...
发送数据
BluetoothGattCharateristic.setValue(byte[]);
BluetoothGatt.writeCharateristic(BluetoothGattCharateristic);
使能Notification及Indication
BluetoothGattDescriptor = BluetoothGattCharateristic.getDescriptor(UUID.fromString());
BluetoothGatt.setCharacteristicNotification(BluetoothGattCharateristic,boolean);
BluetoothGattDescriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
接收数据
接收收据包括读回调,及Notification回调
通常用的比较多的是Notification,因为这种数据传输方法无需确认,速度快。
当收到Notifiation数据时,会触发Gatt回调方法的onCharacteristicChanged()方法被调用
所以可以在这里读取数据
final byte[] buf = characteristic.getValue();
最后当退出时别忘了请求断开链接
BluetoothGatt.close();
BluetoothGatt = null;
蓝牙UUID格式
UUID格式包括16bit格式及128bit格式
其中16bit格式的UUID会在Android自动转换为128bit的UUID格式,其转换方式为:
"0000"+uuid+"-"+uuid_base;
uuid就是我们的16bit 的UUID值
uuid_base为“0000-1000-8000-00805F9B34FB"
所以假设设备上有FFF0的16bit的UUID,则转换为128bit的UUID值为
0000FFF0-0000-1000-8000-00805F9B34FB