与天地兮比寿,与日月兮齐光。这篇文章主要讲述Android nougat(超过7.0.0)的BLE(蓝牙低功耗)无法读取数据相关的知识,希望能为你提供帮助。
首先,我的应用程序无法使用BLE读取牛轧糖中的数据我正在使用BlueNRG-MS模块与设备连接。调用Marshmallow onCharacteristicChanged方法,我可以接收数据。但超过7.0.0 onCharacteristicChanged方法从未调用过。
我搜索了这个,有人告诉我添加这个代码。
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_UUID);
if (descriptor != null) {
descriptor.setValue(enabled ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
但我不确切知道在CLIENT_UUID中输入什么。
这就是我的所有代码。
public class BleManager {private static final String TAG = "BleManager";
static final private UUID CCCD_ID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
public static final int STATE_ERROR = -1;
public static final int STATE_NONE = 0;
// Initialized
public static final int STATE_IDLE = 1;
// Not connected
public static final int STATE_SCANNING = 2;
// Scanning
public static final int STATE_CONNECTING = 13;
// Connecting
public static final int STATE_CONNECTED = 16;
// Connectedpublic static final int MESSAGE_STATE_CHANGE = 1;
public static final int MESSAGE_READ = 2;
public static final int MESSAGE_WRITE = 3;
public static final int MESSAGE_DEVICE_NAME = 4;
public static final int MESSAGE_TOAST = 5;
public static final long SCAN_PERIOD = 5*1000;
private static Context mContext = null;
private static BleManager mBleManager = null;
private final Handler mHandler;
private final BluetoothAdapter mBluetoothAdapter;
private BluetoothAdapter.LeScanCallback mLeScanCallback = null;
private ArrayList<
BluetoothDevice>
mDeviceList = new ArrayList<
BluetoothDevice>
();
private BluetoothDevice mDefaultDevice = null;
private BluetoothGatt mBluetoothGatt = null;
private ArrayList<
BluetoothGattService>
mGattServices
= new ArrayList<
BluetoothGattService>
();
private ArrayList<
BluetoothGattCharacteristic>
mGattCharacteristics
= new ArrayList<
BluetoothGattCharacteristic>
();
private ArrayList<
BluetoothGattCharacteristic>
mWritableCharacteristics
= new ArrayList<
BluetoothGattCharacteristic>
();
private BluetoothGattCharacteristic mDefaultChar = null;
private int mState = -1;
/**
* Constructor. Prepares a new Bluetooth session.
* @param contextThe UI Activity Context
* @param hA Listener to receive messages back to the UI Activity
*/
private BleManager(Context context, Handler h) {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = h;
mContext = context;
if(mContext == null)
return;
}public synchronized static BleManager getInstance(Context c, Handler h) {
if(mBleManager == null)
mBleManager = new BleManager(c, h);
return mBleManager;
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public synchronized void finalize() {
if (mBluetoothAdapter != null) {
mState = STATE_IDLE;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
disconnect();
}mDefaultDevice = null;
mBluetoothGatt = null;
mDefaultService = null;
mGattServices.clear();
mGattCharacteristics.clear();
mWritableCharacteristics.clear();
if(mContext == null)
return;
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void stopScanning() {
if(mState <
STATE_CONNECTING) {
mState = STATE_IDLE;
mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_IDLE, 0).sendToTarget();
}
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private int checkGattServices(List<
BluetoothGattService>
gattServices) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.d(TAG, "# BluetoothAdapter not initialized");
return -1;
}for (BluetoothGattService gattService : gattServices) {
Log.d(TAG, "# GATT Service: "+gattService.toString());
Toast.makeText(mContext, "" + gattService.toString(), Toast.LENGTH_SHORT).show();
mGattServices.add(gattService);
List<
BluetoothGattCharacteristic>
gattCharacteristics = gattService.getCharacteristics();
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
Toast.makeText(mContext, "" + gattCharacteristic.toString(), Toast.LENGTH_SHORT).show();
mGattCharacteristics.add(gattCharacteristic);
Log.d(TAG, "# GATT Char: "+gattCharacteristic.toString());
boolean isWritable = isWritableCharacteristic(gattCharacteristic);
if(isWritable) {
mWritableCharacteristics.add(gattCharacteristic);
}boolean isReadable = isReadableCharacteristic(gattCharacteristic);
if(isReadable) {
readCharacteristic(gattCharacteristic);
}if(isNotificationCharacteristic(gattCharacteristic)) {
setCharacteristicNotification(gattCharacteristic, true);
if(isWritable &
&
isReadable) {
mDefaultChar = gattCharacteristic;
}
}
}
}return mWritableCharacteristics.size();
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private boolean isWritableCharacteristic(BluetoothGattCharacteristic chr) {
if(chr == null) return false;
final int charaProp = chr.getProperties();
if (((charaProp &
BluetoothGattCharacteristic.PROPERTY_WRITE) |
(charaProp &
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) >
0) {
Log.d(TAG, "# Found writable characteristic");
return true;
} else {
Log.d(TAG, "# Not writable characteristic");
return false;
}
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private boolean isReadableCharacteristic(BluetoothGattCharacteristic chr) {
if(chr == null) return false;
final int charaProp = chr.getProperties();
if((charaProp &
BluetoothGattCharacteristic.PROPERTY_READ) >
0) {
Log.d(TAG, "# Found readable characteristic");
return true;
} else {
Log.d(TAG, "# Not readable characteristic");
return false;
}
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private boolean isNotificationCharacteristic(BluetoothGattCharacteristic chr) {
if(chr == null) return false;
final int charaProp = chr.getProperties();
if((charaProp &
BluetoothGattCharacteristic.PROPERTY_NOTIFY) >
0) {
Log.d(TAG, "# Found notification characteristic");
return true;
} else {
Log.d(TAG, "# Not notification characteristic");
return false;
}
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.d(TAG, "# BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.d(TAG, "# BluetoothAdapter not initialized");
return;
}mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CCCD_ID);
if (descriptor != null) {
descriptor.setValue(enabled ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}public void setScanCallback(BluetoothAdapter.LeScanCallback cb) {
mLeScanCallback = cb;
}public int getState() {
return mState;
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean scanLeDevice(final boolean enable) {
boolean isScanStarted = false;
if (enable) {
if(mState == STATE_SCANNING)
return false;
if(mBluetoothAdapter.startLeScan(mLeScanCallback)) {
mState = STATE_SCANNING;
mDeviceList.clear();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
stopScanning();
}
}, SCAN_PERIOD);
mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_SCANNING, 0).sendToTarget();
isScanStarted = true;
}
} else {
if(mState <
STATE_CONNECTING) {
mState = STATE_IDLE;
mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_IDLE, 0).sendToTarget();
}
stopScanning();
}return isScanStarted;
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean connectGatt(Context c, boolean bAutoReconnect, BluetoothDevice device) {
if(c == null || device == null)
return false;
mGattServices.clear();
mGattCharacteristics.clear();
mWritableCharacteristics.clear();
mBluetoothGatt = device.connectGatt(c, bAutoReconnect, mGattCallback);
mDefaultDevice = device;
mState = STATE_CONNECTING;
mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_CONNECTING, 0).sendToTarget();
return true;
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean connectGatt(Context c, boolean bAutoReconnect, String address) {
if(c == null || address == null)
return false;
if(mBluetoothGatt != null &
&
mDefaultDevice != null
&
&
address.equals(mDefaultDevice.getAddress())) {
if (mBluetoothGatt.connect()) {
mState = STATE_CONNECTING;
return true;
}
}BluetoothDevice device =
BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
if (device == null) {
Log.d(TAG, "# Device not found.Unable to connect.");
return false;
}mGattServices.clear();
mGattCharacteristics.clear();
mWritableCharacteristics.clear();
mBluetoothGatt = device.connectGatt(c, bAutoReconnect, mGattCallback);
mDefaultDevice = device;
mState = STATE_CONNECTING;
mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_CONNECTING, 0).sendToTarget();
return true;
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.d(TAG, "# BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
public boolean write(BluetoothGattCharacteristic chr, byte[] data) {
if (mBluetoothGatt == null) {
Log.d(TAG, "# BluetoothGatt not initialized");
return false;
}BluetoothGattCharacteristic writableChar = null;
if(chr == null) {
if(mDefaultChar == null) {
for(BluetoothGattCharacteristic bgc : mWritableCharacteristics) {
if(isWritableCharacteristic(bgc)) {
writableChar = bgc;
}
}
if(writableChar == null) {
Log.d(TAG, "# Write failed - No available characteristic");
return false;
}
} else {
if(isWritableCharacteristic(mDefaultChar)) {
Log.d(TAG, "# Default GattCharacteristic is PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE");
writableChar = mDefaultChar;
} else {
Log.d(TAG, "# Default GattCharacteristic is not writable");
mDefaultChar = null;
return false;
}
}
} else {
if (isWritableCharacteristic(chr)) {
Log.d(TAG, "# user GattCharacteristic is PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE");
writableChar = chr;
} else {
Log.d(TAG, "# user GattCharacteristic is not writable");
return false;
}
}writableChar.setValue(data);
writableChar.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
mBluetoothGatt.writeCharacteristic(writableChar);
mDefaultChar = writableChar;
return true;
}private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
mState = STATE_CONNECTED;
Log.d(TAG, "# Connected to GATT server.");
mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_CONNECTED, 0).sendToTarget();
gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
mState = STATE_IDLE;
Log.d(TAG, "# Disconnected from GATT server.");
mHandler.obtainMessage(MESSAGE_STATE_CHANGE, STATE_IDLE, 0).sendToTarget();
mBluetoothGatt = null;
mGattServices.clear();
mDefaultService = null;
mGattCharacteristics.clear();
mWritableCharacteristics.clear();
mDefaultChar = null;
mDefaultDevice = null;
}
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "# New GATT service discovered.");
checkGattServices(gatt.getServices());
} else {
Log.d(TAG, "# onServicesDiscovered received: " + status);
}
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
// We've received data from remote
Log.d(TAG, "# Read characteristic: "+characteristic.toString());
final byte[] data = https://www.songbingjia.com/android/characteristic.getValue();
if (data != null &
&
data.length >
0) {
final StringBuilder stringBuilder = new StringBuilder(data.length);
stringBuilder.append(data);
Log.d(TAG, stringBuilder.toString());
mHandler.obtainMessage(MESSAGE_READ, byteArrayToHex(data)).sendToTarget();
}if(mDefaultChar == null &
&
isWritableCharacteristic(characteristic)) {
mDefaultChar = characteristic;
}
}
}@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
// We've received data from remote
Log.d(TAG, "# onCharacteristicChanged: "+characteristic.toString());
final byte[] data = https://www.songbingjia.com/android/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(data);
Log.d(TAG, stringBuilder.toString());
mHandler.obtainMessage(MESSAGE_READ, byteArrayToHex(data)).sendToTarget();
}if(mDefaultChar == null &
&
isWritableCharacteristic(characteristic)) {
mDefaultChar = characteristic;
}
}
};
String byteArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder();
for(final byte b: a)
sb.append(String.format("%02x", b&
0xff));
return sb.toString();
}}
答案请尝试以下功能启用蓝牙低功耗特性通知。我没有注意到android 7.0.0以上的任何麻烦。
【Android nougat(超过7.0.0)的BLE(蓝牙低功耗)无法读取数据】当您订阅特征更新时,您应该在onCharacteristicChanged Callback()中获取更新的值。确保,外围设备上的值实际更新; )
private void enableNotifications(BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic characteristic ){UUID CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
byte[] payload =BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE;
bluetoothGatt.setCharacteristicNotification(characteristic, true);
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
CLIENT_CHARACTERISTIC_CONFIG);
if (descriptor == null){
Log.w(TAG, "Notification not supported for characteristic");
return;
}descriptor.setValue(payload);
bluetoothGatt.writeDescriptor(descriptor);
}
推荐阅读
- Android蓝牙聊天示例无效,无法连接设备
- 如何使用applescript打开带有quicktime播放器的MP3()
- Appium(连接到127.0.0.1:4723 [/127.0.0.1]失败:连接被拒绝:连接)
- 使用高CPU时通知。通过AppleScript或Automator()
- 在appengine-web.xml中显示“URI未注册”的Android Studio lint()
- Google Apps脚本 - 复制到现有电子表格
- 带有Firebase的Google App Engine-无法添加依赖项
- 差异b / w在AsyncTask Android中取消(true)和取消(false)
- 如何取消Android中的AsyncTask()