react-native-ble-manager
react-native-ble-manager copied to clipboard
Notification error Set notification failed
Version
-
"react-native-ble-manager": "7.6.1", - "react-native": "0.64.0",
- Android :v 9 with android studio Android Studio Arctic Fox | 2020.3.1 Patch 2
Build #AI-203.7717.56.2031.7678000, built on August 27, 2021 Runtime version: 11.0.10+0-b96-7281165 x86_64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. macOS 11.5.2 GC: G1 Young Generation, G1 Old Generation Memory: 2048M Cores: 4 Registry: external.system.auto.import.disabled=true
Expected behaviour
I work for a startup Which sends an array string to the requests sent via the device via Bluetooth It used to work great for both Android and iOS, IOS working so great now but for Android I get it when I use " BleManager.startNotification " Error " Notification error Set notification failed "
I'll share my code :
`const App = () => { const [isScanning, setIsScanning] = useState(false) const peripherals = new Map(); const [list, setList] = useState([]);
const startScan = () => {
if (!isScanning) {
BleManager.scan([], 3, true).then((results) => {
console.log('Scanning...');
setIsScanning(true);
}).catch(err => {
console.error(err);
});
}
}
const handleStopScan = () => { console.log('Scan is stopped'); setIsScanning(false); }
const handleDisconnectedPeripheral = (data) => { let peripheral = peripherals.get(data.peripheral); if (peripheral) { peripheral.connected = false; peripherals.set(peripheral.id, peripheral); setList(Array.from(peripherals.values())); } console.log('Disconnected from ' + data.peripheral); }
const handleUpdateValueForCharacteristic = (data) => { console.log('Received data from ' + data.peripheral + ' characteristic ' + data.characteristic, data.value); }
const retrieveConnected = () => { BleManager.getConnectedPeripherals([]).then((results) => { if (results.length == 0) { console.log('No connected peripherals') } console.log(results); for (var i = 0; i < results.length; i++) { var peripheral = results[i]; peripheral.connected = true; peripherals.set(peripheral.id, peripheral); setList(Array.from(peripherals.values())); } }); }
const handleDiscoverPeripheral = (peripheral) => { console.log('Got ble peripheral', peripheral); if (!peripheral.name) { peripheral.name = 'NO NAME'; } peripherals.set(peripheral.id, peripheral); setList(Array.from(peripherals.values())); }
const testPeripheral = (peripheral) => { if (peripheral){ if (peripheral.connected){ BleManager.disconnect(peripheral.id); }else{ BleManager.connect(peripheral.id).then(() => { let p = peripherals.get(peripheral.id); if (p) { p.connected = true; peripherals.set(peripheral.id, p); setList(Array.from(peripherals.values())); } console.log('Connected to ' + peripheral.id);
setTimeout(() => {
BleManager.retrieveServices(peripheral.id).then((peripheralData) => {
console.log('Retrieved peripheral services', peripheralData);
const data = stringToBytes('@mamin#');
let service_id =
Platform.OS === 'ios'
? peripheralData.characteristics[1].service
: peripheralData.characteristics[4].service;
let characteristic_id =
Platform.OS === 'ios'
? peripheralData.characteristics[1].characteristic
: peripheralData.characteristics[4].characteristic;
console.log('peripheralId~~>', peripheralData.id);
console.log('serviceUUID~~>', service_id);
console.log('characteristicUUID~~~~>', characteristic_id);
BleManager.write(
peripheralData.id,
service_id,
characteristic_id,
data,
)
.then(() => {
console.log('Write: ---- Success --- ');
})
.catch(error => {
console.log(error);
});
BleManager.startNotification(
peripheralData.id,
service_id,
characteristic_id,
1234
)
.then(() => {
console.log('Started notification on ' + pair_d.id);
})
.catch(error => {
console.log('Notification error', error);
});
BleManager.readRSSI(peripheral.id).then((rssi) => {
console.log('Retrieved actual RSSI value', rssi);
let p = peripherals.get(peripheral.id);
if (p) {
p.rssi = rssi;
peripherals.set(peripheral.id, p);
setList(Array.from(peripherals.values()));
}
});
});
}, 900);
}).catch((error) => {
console.log('Connection error', error);
});
}
}
}
useEffect(() => { BleManager.start({showAlert: false});
bleManagerEmitter.addListener('BleManagerDiscoverPeripheral', handleDiscoverPeripheral);
bleManagerEmitter.addListener('BleManagerStopScan', handleStopScan );
bleManagerEmitter.addListener('BleManagerDisconnectPeripheral', handleDisconnectedPeripheral );
bleManagerEmitter.addListener('BleManagerDidUpdateValueForCharacteristic', handleUpdateValueForCharacteristic );
if (Platform.OS === 'android' && Platform.Version >= 23) {
PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION).then((result) => {
if (result) {
console.log("Permission is OK");
} else {
PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION).then((result) => {
if (result) {
console.log("User accept");
} else {
console.log("User refuse");
}
});
}
});
}
return (() => {
console.log('unmount');
bleManagerEmitter.removeListener('BleManagerDiscoverPeripheral', handleDiscoverPeripheral);
bleManagerEmitter.removeListener('BleManagerStopScan', handleStopScan );
bleManagerEmitter.removeListener('BleManagerDisconnectPeripheral', handleDisconnectedPeripheral );
bleManagerEmitter.removeListener('BleManagerDidUpdateValueForCharacteristic', handleUpdateValueForCharacteristic );
})
}, []);
const renderItem = (item) => { const color = item.connected ? 'green' : '#fff'; return ( <TouchableHighlight onPress={() => testPeripheral(item) }> <View style={[styles.row, {backgroundColor: color}]}> <Text style={{fontSize: 12, textAlign: 'center', color: '#333333', padding: 10}}>{item.name}</Text> <Text style={{fontSize: 10, textAlign: 'center', color: '#333333', padding: 2}}>RSSI: {item.rssi}</Text> <Text style={{fontSize: 8, textAlign: 'center', color: '#333333', padding: 2, paddingBottom: 20}}>{item.id}</Text> </View> </TouchableHighlight> ); }
return ( <> <StatusBar barStyle="dark-content" /> <SafeAreaView> <ScrollView contentInsetAdjustmentBehavior="automatic" style={styles.scrollView}> {global.HermesInternal == null ? null : ( <View style={styles.engine}> <Text style={styles.footer}>Engine: Hermes</Text> </View> )} <View style={styles.body}>
<View style={{margin: 10}}>
<Button
title={'Scan Bluetooth (' + (isScanning ? 'on' : 'off') + ')'}
onPress={() => startScan() }
/>
</View>
<View style={{margin: 10}}>
<Button title="Retrieve connected peripherals" onPress={() => retrieveConnected() } />
</View>
{(list.length == 0) &&
<View style={{flex:1, margin: 20}}>
<Text style={{textAlign: 'center'}}>No peripherals</Text>
</View>
}
</View>
</ScrollView>
<FlatList
data={list}
renderItem={({ item }) => renderItem(item) }
keyExtractor={item => item.id}
/>
</SafeAreaView>
</>
); };
const styles = StyleSheet.create({
scrollView: {
backgroundColor: Colors.lighter,
},
engine: {
position: 'absolute',
right: 0,
},
body: {
backgroundColor: Colors.white,
},
sectionContainer: {
marginTop: 32,
paddingHorizontal: 24,
},
sectionTitle: {
fontSize: 24,
fontWeight: '600',
color: Colors.black,
},
sectionDescription: {
marginTop: 8,
fontSize: 18,
fontWeight: '400',
color: Colors.dark,
},
highlight: {
fontWeight: '700',
},
footer: {
color: Colors.dark,
fontSize: 12,
fontWeight: '600',
padding: 4,
paddingRight: 12,
textAlign: 'right',
},
})
;`
@marcosinigaglia Please save my life :(((( Thank You
Hi @AMINDRH91 , are you sure that the characteristic can notify?
Have close issue, but in adb logs seems like all is ok, but I catch error like set notificatoin failed for <Char UUID>
No it's Open issue i did not get answer yet @TyshkevichSergey
Yes, It's working great on the IOS , but in the android send notification not work
Any progress on this?
I'm having a similar issue... It works fine in iOS, but all Android versions (we've tested 9 and 12 at this point) are giving the same issue as above.
To reiterate the problem I believe we're facing:
- We subscribe to notifications on characteristic A
- We try and read a value from characteristic B
- We successfully get the value from characteristic B
- We see an error with the notification
Failed to set client characteristic notification for UUID-for-characteristic-A
Anyone figured out why this is happening? Bump @marcosinigaglia
I believe you need to add the listener after you start notifications for all characteristics:
setNotifyOnUpdate = async (): Promise<boolean> => {
await this.bleManager.startNotification(this.peripheralId, <service>, <characteristicA>)
await this.bleManager.startNotification(this.peripheralId, <service>, <characteristicB>)
// only do this once you've started notifications for all the characteristics you want...
bleManagerEmitter.addListener(
"BleManagerDidUpdateValueForCharacteristic",
this.handleUpdateValueForCharacteristic
)
}
Your logic to handle notifications would be in handleUpdateValueForCharacteristic().
Is the ble server (the device your app should communicate with) is built by your company? If so, throwing a wild guess to the air here, but they might forgot, or didnt see a reason to add descriptors to their bluetooth characteristics.
Heres my reasoning:
private void setNotify(UUID serviceUUID, UUID characteristicUUID, final Boolean notify, Callback callback) {
if (!isConnected() || gatt == null) {
callback.invoke("Device is not connected", null);
completedCommand();
return;
}
BluetoothGattService service = gatt.getService(serviceUUID);
final BluetoothGattCharacteristic characteristic = findNotifyCharacteristic(service, characteristicUUID);
if (characteristic == null) {
callback.invoke("Characteristic " + characteristicUUID + " not found");
completedCommand();
return;
}
if (!gatt.setCharacteristicNotification(characteristic, notify)) {
callback.invoke("Failed to register notification for " + characteristicUUID);
completedCommand();
return;
}
final BluetoothGattDescriptor descriptor = characteristic
.getDescriptor(UUIDHelper.uuidFromString(CHARACTERISTIC_NOTIFICATION_CONFIG));
if (descriptor == null) {
callback.invoke("Set notification failed for " + characteristicUUID);
completedCommand();
return;
}
this is from Peripheral.java in this lib, as you can see, the they check if you have a descriptor, and if you don't they break the function. Im no Java developer, nor I have any deep knowlage on ble technologies, but solely from reading the code after this check it seems that descriptors are the metadata of the characteristics, and the lib uses them to know on which characteristic you've "started notifications" on. Thus, if you don't have any descriptors on the characteristics you want to start notification on, it will fail, so just verify that.