Central manager method is not being called .. - ios

i am new to iOS any one please give some suggestion to me.My process to get status about the bluetooth ring scanner. The bluetooth scanner is working fine and my app getting data form the scanner. But now my task is, whenever i open my app ring scanner should connect automatically. and also i want to display the bluetooth status icon in my app.
1) Ring scanner connected already or connected when my app launch - Bluetooth icon (Blue Colour)
2) Ring Scanner not connected - Bluetooth icon (Red colour)
3) Ring Scanner lost connection or sleep due to lack of activity - Bluetooth icon (Grey colour).
i have started working on this concept but centralManager method is not getting called. Here is my code. any one please help me
h.file
#import <CoreBluetooth/CoreBluetooth.h>
#property (nonatomic, strong) NSString *connected;
#property (nonatomic) CBCentralManager *bluetoothManager;
m.file
- (void)viewDidLoad
{
[super viewDidLoad];
_bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self
queue:nil
options:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0]
forKey:CBCentralManagerOptionShowPowerAlertKey]];
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
NSString *stateString = nil;
switch(_bluetoothManager.state)
{
case CBCentralManagerStateResetting: stateString = #"The connection with the system service was momentarily lost, update imminent."; break;
case CBCentralManagerStateUnsupported: stateString = #"The platform doesn't support Bluetooth Low Energy."; break;
case CBCentralManagerStateUnauthorized: stateString = #"The app is not authorized to use Bluetooth Low Energy."; break;
case CBCentralManagerStatePoweredOff: stateString = #"Bluetooth is currently powered off.";
{
UIAlertView *BluetoothOff = [[UIAlertView alloc] initWithTitle:#"Warning!!" message:#"Turn ON Bluetooth in setting!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[BluetoothOff show];
}
break;
case CBCentralManagerStatePoweredOn: stateString = #"Bluetooth is currently powered on and available to use.";
{
// [self.bluetoothManager scanForPeripheralsWithServices:nil options:nil];
[self startScan];
}
break;
default: stateString = #"State unknown, update imminent.";
break;
}
NSLog(#"Bluetooth State: %#",stateString);
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral*)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(#"DiscoverPeripheral#");
}
-(void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
{
NSLog(#"RetrievePeripherals#");
}
-(void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals
{
NSLog(#"RetrieveConnectedPeripherals#");
}
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(#"Connection Failed#");
}
-(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
NSLog(#"Disconnected#");
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
[peripheral setDelegate:self];
[peripheral discoverServices:nil];
self.connected = [NSString stringWithFormat:#"Connected: %#", peripheral.state == CBPeripheralStateConnected ? #"YES" : #"NO"];
}
- (void) startScan
{
NSLog(#"Start scanning");
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
[self.bluetoothManager scanForPeripheralsWithServices:nil options:options];
}

You just save the UUID of the peripheral in your internal database and try to reconnect it after the application launched using the same UUID.
Save it in
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
NSLog(#"peripheral.identifier=%#",peripheral.identifier.UUIDString);
}
After connecting with the peripheral you can read any value provided by the scanner.

Related

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];
}

Detect Siri Remote from iPhone via Bluetooth

Is it possible to detect the Apple TV 4 Siri Remote from an iOS application using CoreBluetooth? I'm able to detect the Apple TV, but I'm not having any luck detecting the Siri Remote. The Siri Remote uses Bluetooth 4.0 so I'm assuming it is detectable. Ideally, I'd like to detect the Siri Remote even if it's already paired with the Apple TV.
Simply being able to detect any signal from the Siri Remote/know it's in the vicinity of the users iPhone is what I'm after.
#import "ViewController.h"
#import CoreBluetooth;
#interface ViewController () <CBPeripheralDelegate, CBCentralManagerDelegate>
#end
#implementation ViewController {
CBCentralManager *btManager;
}
-(void)viewDidLoad {
[super viewDidLoad];
btManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
#pragma mark - CBCentralManagerDelegate Methods
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(#"peripheral name: %#", peripheral.name);
NSLog(#"peripheral services: %#", peripheral.services);
NSLog(#"peripheral identifier: %#", peripheral.identifier);
NSLog(#"peripheral state: %ld", (long)peripheral.state);
NSLog(#"RSSI: %# \n\n", RSSI);
}
-(void)centralManagerDidUpdateState:(CBCentralManager *)central {
NSString *nsLogMessage;
switch (central.state) {
case CBCentralManagerStateUnknown: {
nsLogMessage = [NSString stringWithFormat:#"State unknown, update imminent."];
break;
}
case CBCentralManagerStateResetting: {
nsLogMessage = [NSString stringWithFormat:#"The connection with the system service was momentarily lost, update imminent."];
break;
}
case CBCentralManagerStateUnsupported: {
nsLogMessage = [NSString stringWithFormat:#"The platform doesn't support Bluetooth Low Energy"];
break;
}
case CBCentralManagerStateUnauthorized: {
nsLogMessage = [NSString stringWithFormat:#"The app is not authorized to use Bluetooth Low Energy"];
break;
}
case CBCentralManagerStatePoweredOff: {
nsLogMessage = [NSString stringWithFormat:#"Bluetooth is currently powered off."];
break;
}
case CBCentralManagerStatePoweredOn: {
nsLogMessage = [NSString stringWithFormat:#"Bluetooth is currently powered on and available to use."];
NSDictionary *scanningOptions = #{CBCentralManagerScanOptionAllowDuplicatesKey: #YES};
[btManager scanForPeripheralsWithServices:nil options:scanningOptions];
break;
}
}
NSLog(#"%#", nsLogMessage);
}

didDiscoverPeripheral never called

I have two devices (ipad 3 and iphone 4s), and was trying to find a way to recognize one of the two devices (For future exchange information between them), for that, I'm with active Bluetooth devices in 2, and using the following code:
- (void)viewDidLoad {
[super viewDidLoad];
CBUUID *otherDevice = [CBUUID UUIDWithString:#"180A"];
NSDictionary *scanOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
self.mgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[self.mgr scanForPeripheralsWithServices:[NSArray arrayWithObject:otherDevice] options:scanOptions];
}
#pragma mark - delegates
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(#"I found new devices -> %#",[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 CBCentralManagerStatePoweredOn:
{
messtoshow=[NSString stringWithFormat:#"Bluetooth is currently powered on and available to use."];
[self.mgr scanForPeripheralsWithServices:nil options:nil];
break;
}
}
NSLog(#"%#",messtoshow);
}
The problem with this code is that I am getting the message on the console that bluetooth is active, but the method 'didDiscoverPeripheral:' not being called, why this is happening? (since the Bluetooth on both devices are active)?

Could you advise to discover any bluetooth device on iOS?

I try to make program to detect uncertain Bluetooth device at iOS.
The device scanning work well but it could not detect any device. However in the basic option in Ipad, the bluetooth devices were detected well. Bellow show the my code. Please advise to fix some problem.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//CB setup
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:dispatch_get_main_queue()];
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
// You should test all scenarios
if (central.state != CBCentralManagerStatePoweredOn) {
return;
}
if (central.state == CBCentralManagerStatePoweredOn) {
_scan_state = 1;
}
[self deviceScan];
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
NSLog(#"dicovered: %#", peripheral.name);
if(![self.BTNames containsObject:peripheral]){
[self.BTNames addObject:peripheral];
}
_num_cell = self.BTNames.count;
[self.BTList reloadData];
}
- (void) deviceScan{
if(_scan_state){
/* [_centralManager scanForPeripheralsWithServices:nil options:#{ CBCentralManagerScanOptionAllowDuplicatesKey : #NO }];*/
[_centralManager scanForPeripheralsWithServices:nil options:nil];
NSLog(#"Scan Starting");
}
}

CBCentralManager scanForPeripheralsWithServices:nil is not returning any results

I am trying to display all available BLE beacons. I got some Estimote and Kontakt.io beacons with me and for some reason the below BLE scanning code does not find any of them.
I went through all the possible SO questions relating to BLE discovery and that codes is exactly as in other places.
App source code here
- (void)viewDidLoad {
[super viewDidLoad];
self.manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
/*
Request CBCentralManager to scan for all available services
*/
- (void) startScan
{
NSLog(#"Start scanning");
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
[self.manager scanForPeripheralsWithServices:nil options:options];
}
This delegate method never gets called
/*
Invoked when the central discovers bt peripheral while scanning.
*/
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)aPeripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(#"THIS NEVER GETS CALLED");
}
iBeacon's aren't accessed as peripherals - they are beacons. They are handled through the Core Location framework, not the Core Bluetooth framework.
There may be vendor specific services advertised by the beacons that can be detected by Core Bluetooth.
Your code doesn't wait until the CBCentralManager is in the powered on state. I made the following changes and it worked on both iOS 7.1 and iOS8 -
- (void)viewDidLoad {
[super viewDidLoad];
self.manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
- (void) startScan
{
NSLog(#"Start scanning");
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
[self.manager scanForPeripheralsWithServices:nil options:options];
}
- (BOOL) isLECapableHardware
{
NSString * state = nil;
switch ([self.manager state])
{
case CBCentralManagerStateUnsupported:
state = #"The platform/hardware doesn't support Bluetooth Low Energy.";
break;
case CBCentralManagerStateUnauthorized:
state = #"The app is not authorized to use Bluetooth Low Energy.";
break;
case CBCentralManagerStatePoweredOff:
state = #"Bluetooth is currently powered off.";
break;
case CBCentralManagerStatePoweredOn:
[self startScan];
return TRUE;
case CBCentralManagerStateUnknown:
default:
return FALSE;
}
NSLog(#"Central manager state: %#", state);
UIAlertView *alert = [[UIAlertView alloc] init];
[alert setMessage:state];
[alert addButtonWithTitle:#"OK"];
[alert show];
return FALSE;
}
The problem was posed by the version of the OS I was testing it with.
Let's just say this version that I was testing was 4+4 (as it is under the NDA)
Apparently that new version will abort scanning if you trigger
[self.manager scanForPeripheralsWithServices:nil options:options];
before
CBCentralManagerStatePoweredOn is ON
So simply starting scanning after that state made it work for me.
#pragma mark - CBCentralManager delegate methods
/*
Invoked whenever the central manager's state is updated.
*/
- (void) centralManagerDidUpdateState:(CBCentralManager *)central
{
[self isLECapableHardware]? NSLog(#"YES"):NSLog(#"NO");
}
- (BOOL) isLECapableHardware
{
NSString * state = nil;
switch ([self.manager state])
{
case CBCentralManagerStateUnsupported:
state = #"The platform/hardware doesn't support Bluetooth Low Energy.";
break;
case CBCentralManagerStateUnauthorized:
state = #"The app is not authorized to use Bluetooth Low Energy.";
break;
case CBCentralManagerStatePoweredOff:
state = #"Bluetooth is currently powered off.";
break;
case CBCentralManagerStatePoweredOn:
//---> HERE
[self startScan];
return TRUE;
case CBCentralManagerStateUnknown:
default:
return FALSE;
}
return FALSE;
}
I downloaded your code and found there was no call to startScan. Once I added that it worked for me. I added some details to the logging like this:
- (void) centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)aPeripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(#"Discovered %# %#", aPeripheral, advertisementData);
}
and I get this output:
2014-09-08 15:17:11.827 BTTest[4266:60b] New state 5
2014-09-08 15:17:11.830 BTTest[4266:60b] YES
2014-09-08 15:17:11.831 BTTest[4266:60b] Start scanning
2014-09-08 15:17:11.842 BTTest[4266:60b] CoreBluetooth[WARNING] <CBCentralManager: 0x17d6e5d0> is disabling duplicate filtering, but is using the default queue (main thread) for delegate events
2014-09-08 15:17:12.438 BTTest[4266:60b] per <CBPeripheral: 0x17d91220 identifier = C6E33BA0-F6E7-5830-0643-A47855AD27B9, Name = "(null)", state = disconnected> {
kCBAdvDataChannel = 37;
kCBAdvDataIsConnectable = 1;
}
2014-09-08 15:17:12.595 BTTest[4266:60b] per <CBPeripheral: 0x17d89b60 identifier = 4FF1E398-E24C-8739-A19B-9DF8A2A5493B, Name = "Flex", state = disconnected> {
kCBAdvDataChannel = 38;
kCBAdvDataIsConnectable = 1;
kCBAdvDataLocalName = Flex;
kCBAdvDataServiceData = {
"Device Information" = <0704>;
};
kCBAdvDataServiceUUIDs = (
"ADABFB00-6E7D-4601-BDA2-BFFAA68956BA"
);
kCBAdvDataTxPowerLevel = "-6";
}

Resources