iOS/Objective-C: BLE in Peripheral mode doesn't work
You are probably adding the service transferService
too early to the peripheral manager and you are also probably starting the advertisement too early.
You have to wait until peripheralManagerDidUpdateState
reports that your peripheral manager's state has reached CBPeripheralManagerStatePoweredOn
.
This said, you can either move the code from RCT_EXPORT_METHOD(start:(NSDictionary *)options)
into your empty peripheralManagerDidUpdateState
implementation.
Alternatively, if you only want to add services to your peripheralManager
and then start advertising when somebody has called your start
method (looks like you're creating a React Native binding?), make sure that self.peripheralManager.state
is CBPeripheralManagerStatePoweredOn
within your start
method. This however requires the caller of start
(your React Native JS code) to not call this method too early.
RCT_EXPORT_METHOD(start:(NSDictionary *)options){ NSLog(@"Start?"); if (self.peripheralManager.state != CBPeripheralManagerStatePoweredOn) { NSLog(@"Peripheral is not powered on"); return; } if (self.centralManager.state != CBCentralManagerStatePoweredOn) { NSLog(@"Central is not powered on"); return; } NSLog(@"OK, peripheral and central are both powered on"); [self.centralManager scanForPeripheralsWithServices:nil options:nil]; self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:@"EB6727C4-F184-497A-A656-76B0CDAC633A"] properties:CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable]; CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:@"EB6727C4-F184-497A-A656-76B0CDAC633A"] primary:YES]; transferService.characteristics = @[self.transferCharacteristic]; [self.peripheralManager addService:transferService]; [self.peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:@"FB694B90-F49E-4597-8306-171BBA78F846"]] }]; NSLog(@"Started");}
Similarly you can only start scanning for peripherals with your centralManager
if it has the "powered on" state.
Apparently, there is no way to programmatically turn the Bluetooth on in iOS as well as the pairing is not possible programmatically right now.
However, we can intimate user to turn on the Bluetooth via alert as below in RCT_EXPORT_METHOD(start:(NSDictionary *)options) method.
if(peripheralManager.state < CBPeripheralManagerStatePoweredOn){{ //Show alert to user to turn on the Bluetooth and it will go to peripheralManagerDidUpdateState when user turn it on.}else{ //You can continue setting up the data.}