didDiscoverPeripheral not been called after advertising another iOS device - ios

basically i have two apps, one for scanning for bluetooth devices and the other for advertising, and what i am trying to do is to get a list of all iOS devices, within my proximity on the app which scans for the iOS device .
This is my code so far:
Scanning.m:
// Scan for all available CoreBluetooth LE devices
NSDictionary *scanOptions = #{CBCentralManagerScanOptionAllowDuplicatesKey:#(YES)};
NSArray *services = #[[CBUUID UUIDWithString:#"1CC024D6-E413-4B56-993C-831CAF033366"]];
[self.centralManager scanForPeripheralsWithServices:services options:scanOptions];
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(#"RSSI: %d", [RSSI intValue]);
}
// method called whenever the device state changes.
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
// Determine the state of the peripheral
if ([central state] == CBCentralManagerStatePoweredOff) {
NSLog(#"CoreBluetooth BLE hardware is powered off");
}
else if ([central state] == CBCentralManagerStatePoweredOn) {
NSLog(#"CoreBluetooth BLE hardware is powered on and ready");
}
else if ([central state] == CBCentralManagerStateUnauthorized) {
NSLog(#"CoreBluetooth BLE state is unauthorized");
}
else if ([central state] == CBCentralManagerStateUnknown) {
NSLog(#"CoreBluetooth BLE state is unknown");
}
else if ([central state] == CBCentralManagerStateUnsupported) {
NSLog(#"CoreBluetooth BLE hardware is unsupported on this platform");
}
}
Advertising.m:
self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
[self listenForRelays];
/** Required protocol method. A full app should take care of all the possible states,
* but we're just waiting for to know when the CBPeripheralManager is ready
*/
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
{
if (peripheral.state == CBPeripheralManagerStatePoweredOn)
{
// We're in CBPeripheralManagerStatePoweredOn state...
NSLog(#"self.peripheralManager powered on.");
// ... so build our service.
}
}
-(void) listenForRelays {
if(self.peripheralManager.state == CBPeripheralManagerStatePoweredOn)
{
NSDictionary *advertisingData = #{CBAdvertisementDataLocalNameKey:#"my-peripheral",
CBAdvertisementDataServiceUUIDsKey:#[[CBUUID UUIDWithString:#"1CC024D6-E413-4B56-993C-831CAF033322"]]};
// Start advertising over BLE
[self.peripheralManager startAdvertising:advertisingData];
}
}
When i run the different apps on different iphones, nothing happens !
This doesn't crash but didDiscoverPeripheral never gets called :( please help me out ! and yes i have gone through the documentation but still no good :((
cheers

You can't initiate your scan until after you are in the powered-on state - use code in your scanning app similar to that which is in your advertising app.
In iOS 7 starting the scan before you were powered on issued a warning on the console, but it still worked. In iOS 8 it doesn't work.

Related

How to scan and connect to Bluetooth A2DP device on iOS programmatically

I have built an Android APP which handles the scan, return nearby devices, and connect steps on both BLE and Bluetooth A2DP, and it works well. Now I’m developing the iOS version which is with exactly the same functionalities. For the BLE part, I can use CoreBluetooth to perform what I need without any problems, yet I don’t know how to implement the steps of “scan -> return nearby discoverable devices -> connect” on iOS for Bluetooth A2DP device. The only solution I’ve found so far is to navigate to Settings page from my iOS APP and perform the connection on it. Is there any way to implement the Bluetooth A2DP connection process inside of my iOS APP programmatically?
in iOS, bluetooth works on central peripheral concept. below is the how it scan for nearby devices.
#import <UIKit/UIKit.h>
#import <CoreBluetooth/CoreBluetooth.h>
#interface MyViewController : UIViewController <CBPeripheralDelegate, CBCentralManagerDelegate>
{
CBCentralManager *mgr;
}
#property (readwrite, nonatomic) CBCentralManager *mgr;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
mgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog([NSString stringWithFormat:#"%#",[advertisementData description]]);
}
-(void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals{
NSLog(#"This is it!");
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
NSString *messtoshow;
switch (central.state) {
case CBCentralManagerStateUnknown:
{
messtoshow=[NSString stringWithFormat:#"State unknown, update imminent."];
break;
}
case CBCentralManagerStateResetting:
{
messtoshow=[NSString stringWithFormat:#"The connection with the system service was momentarily lost, update imminent."];
break;
}
case CBCentralManagerStateUnsupported:
{
messtoshow=[NSString stringWithFormat:#"The platform doesn't support Bluetooth Low Energy"];
break;
}
case CBCentralManagerStateUnauthorized:
{
messtoshow=[NSString stringWithFormat:#"The app is not authorized to use Bluetooth Low Energy"];
break;
}
case CBCentralManagerStatePoweredOff:
{
messtoshow=[NSString stringWithFormat:#"Bluetooth is currently powered off."];
break;
}
case CBCentralManagerStatePoweredOn:
{
messtoshow=[NSString stringWithFormat:#"Bluetooth is currently powered on and available to use."];
[mgr scanForPeripheralsWithServices:nil options:nil];
//[mgr retrieveConnectedPeripherals];
//--- it works, I Do get in this area!
break;
}
}
NSLog(messtoshow);
}

peripheral:didUpdateValueForCharacteristic:error: not called

I am building an iOS application which connects to a Bluetooth device to turn some lights on and off. For these actions, I need to be paired with the device. There is also a battery service for which I do not. The situation where I connect the device for the first time (not paired before) it works like it supposed to work. I can connect when the device is in pairing mode, get a pair request and read/write the values. When I connect the device to an other device (Android in this case, but I don't think it matters much) and try to run the iOS application, it can connect to a device, discover services and the characteristics for those services, but it can't read/write those values.
The method [peripheral readValueForCharacteristic:characteristic]; isn't called when I try to read all characteristics. I also tried using the setNotifyValue method with no success. When I try to read only the battery service, it works, but when the other services are enabled (which I need to be paired for) it doesn't.
When I remove the device from the Bluetooth settings and run the application again, it works like the first time and does all the things it should. Even reconnecting the devices the next day.
The question is, how can I read/write those values again without removing the device in the settings screen? Can I remove the device in the application without requiring the user to go to the Bluetooth settings? Or is it something that has to be changed on the firmware of the device?
This is (part) of my Bluetooth logic:
- (void)changeState:(BluetoothState)state { if ([[self delegate] respondsToSelector:#selector(bluetoothChangedState:)]) [[self delegate] bluetoothChangedState:state]; }
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
switch ([central state]) {
case CBCentralManagerStateUnknown: { NSLog(#"centralManagerDidUpdateState:CBCentralManagerStateUnknown"); break; }
case CBCentralManagerStateResetting: { NSLog(#"centralManagerDidUpdateState:CBCentralManagerStateResetting"); break; }
case CBCentralManagerStateUnauthorized: { NSLog(#"centralManagerDidUpdateState:CBCentralManagerStateUnauthorized"); break; }
case CBCentralManagerStatePoweredOff: { [self changeState:BluetoothStateOff]; break; }
case CBCentralManagerStateUnsupported: { [self changeState:BluetoothStateUnsupported]; break; }
case CBCentralManagerStatePoweredOn: { [self changeState:BluetoothStateOn]; [central scanForPeripheralsWithServices:nil options:nil]; break; }
}
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
if ([[peripheral name] isEqualToString:#"Glasses"]) { // #TODO better check for glasses.
[[self bluetoothManager] stopScan];
[peripheral setDelegate:self];
[self setPeripheral:peripheral];
[[self bluetoothManager] connectPeripheral:peripheral options:nil];
}
return;
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
[peripheral setDelegate:self];
[peripheral discoverServices:nil];
[self setConnected:peripheral.state == CBPeripheralStateConnected];
if ([self isConnected]) [[self delegate] bluetoothDidConnect];
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
for (CBService *service in [peripheral services]) {
[peripheral discoverCharacteristics:nil forService:service];
}
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
if ([[service UUID] isEqual:[CBUUID UUIDWithString:UID]]) {
for (CBCharacteristic *characteristic in [service characteristics]) {
if (![[characteristic UUID] isEqual:[CBUUID UUIDWithString:UID_UNKNOWN]]) {
[peripheral readValueForCharacteristic:characteristic];
}
}
} else if ([[service UUID] isEqual:[CBUUID UUIDWithString:BAS]]) {
for (CBCharacteristic *characteristic in [service characteristics]) {
[peripheral readValueForCharacteristic:characteristic];
//[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
NSLog(#"peripheral didUpdateValueForCharacteristic:%#", [characteristic UUID]);
if ([[characteristic UUID] isEqual:[CBUUID UUIDWithString:UID_ENABLED_LEDS]]) [self getEnabledLEDs:characteristic];
else if ([[characteristic UUID] isEqual:[CBUUID UUIDWithString:BAS_BATTERY_LEVEL]]) [self getBatteryLevel:characteristic];
}

automatically connect to bluetooth device without pairing

is it possible to configure a bluetooth-device in a way that my app automatically connects to it when near - without pairing etc.?
The device will be custom built and the app will be written by me, I first have to define some specs. It would be great if there's an option in the device that as soon as it's near my (opened) app that both are connected automatically without any setup process.
Sure you can. If the device will be custom made and you know its characteristics
Code below (TRANSFER_SERVICE_UUID - GUID of your device):
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
// You should test all scenarios
if (central.state != CBCentralManagerStatePoweredOn) {
[self stop];
return;
}
if (central.state == CBCentralManagerStatePoweredOn) {
// Scan for devices
[_centralManager scanForPeripheralsWithServices:#[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] options:#{ CBCentralManagerScanOptionAllowDuplicatesKey : #YES }];
NSLog(#"Scanning started");
if(_delegate)
{
if([_delegate respondsToSelector:#selector(CB_changedStatus:message:)])
{
[_delegate CB_changedStatus:CBManagerMessage_ScanningStarted message:#"Scanning started"];
}
}
}
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(#"Discovered %# at %#", peripheral.name, RSSI);
if (_discoveredPeripheral != peripheral) {
// Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it
_discoveredPeripheral = peripheral;
// And connect
NSLog(#"Connecting to peripheral %#", peripheral);
if(_delegate)
{
if([_delegate respondsToSelector:#selector(CB_changedStatus:message:)])
{
[_delegate CB_changedStatus:CBManagerMessage_ConnectingToPeripheral message:[NSString stringWithFormat:#"Connecting to peripheral %#", peripheral]];
}
}
[_centralManager connectPeripheral:peripheral options:nil];
}
}

Get List of discoverable Bluetooth devices and already paired devices in iOS using CoreBluetooth Framework?

I am trying to get the list of all the nearby bluetooth device and paired device of any kind of bluetooth device in IOS8 and above using CoreBluetooth framework. I am using below method to get the list of all the nearby available bluetooth device but the method is not being called.
- (void)viewDidLoad
{
[super viewDidLoad];
// Start up the CBCentralManager
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
// And somewhere to store the incoming data
_data = [[NSMutableData alloc] init];
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if (central.state != CBCentralManagerStatePoweredOn) {
// In a real app, you'd deal with all the states correctly
return;
}
// The state must be CBCentralManagerStatePoweredOn...
// ... so start scanning
[self scan];
}
- (void)scan
{
[self.centralManager scanForPeripheralsWithServices:nil
options:nil];
NSLog(#"Scanning started");
}
- (void)centralManager:(CBCentralManager *)central
didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary *)advertisementData
RSSI:(NSNumber *)RSSI
{
NSString *thePeripheralName = peripheral.name;
}
I am able to perform both the tasks using BluetoothManager Framework but that is private framework of Apple and Apple Itunes will not approve my application to publish live.

iPhone is not discoverable over bluetooth low energy

I am using CoreBluetooth Framework. I created the demo app to discover the bluetooth low energy devices. As iPhone 4s and above devices supports Bluetooth Low Energy, Am not able to discover another iOS devices over Bluetooth Low Energy from my demo app.
My iPhone has iOS7 running.
Here is my code. I am trying to discover another iPhone from my iOS app. I created Central Demo App. Do I need to create another demo app for peripheral and deploy it on another iPhone, which i wand to discover?.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
// You should test all scenarios
if (central.state == CBCentralManagerStateUnsupported) {
return;
}
if (central.state == CBCentralManagerStatePoweredOn) {
// Scan for devices
[self.centralManager scanForPeripheralsWithServices:nil options:nil];
NSLog(#"Scanning started");
}
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(#"Discovered %# at %#", peripheral.name, RSSI);
}

Resources