Check if Bluetooth is Enabled? - iphone

I just want to do a simple check of whether bluetooth is enabled on the device or not.
I don't want to change the status from inside an app (or at all), use private API's, jailbreak a device, or do anything that would cause Apple to reject an app.
All I want is to know whether bluetooth is turned on or not.
Can anyone shed any light on this? Is there any Apple-allowed way to do this?
I am fully aware, after reading countless posts and documentation that Apple is very restrictive when it comes to Bluetooth (among other things).
If you are only able to contribute to this question with a link to documentation and/or some snide remark about learning objective-c, reading documentation, etc., then please don't respond.

The only way I've ever found to do this is with private frameworks (like Bluetooth Manager, for one) that are only useful for Jailbroken apps... and Apple will reject any app using a private framework. I believe it's even against their ToS to do anything with bluetooth, so you're out of luck there.

There seems to be an answer here - Using Core bluetooth framework
However, that answer will only work for iOS 5.0 and up. I haven't tested this myself, but will return and add feedback if I find that it works.

You can now check this using the CBCentralManager in iOS 7 and initialize it with the CBCentralManagerOptionShowPowerAlertKey option set.
The CBCentralManagerOptionShowPowerAlertKey key, which can be passed to the initWithDelegate:queue:options: method on CBCentralManager which will cause iOS to start the Central Manager & not prompt the user to enable bluetooth.
Posted here: http://chrismaddern.com/determine-whether-bluetooth-is-enabled-on-ios-passively/

Unfortunately not, the SDK does not expose Bluetooth methods.
There may be a way to do it by using undocumented methods, however we all know the problem there.

For iOS9+, you can check my answer here.
#import <CoreBluetooth/CoreBluetooth.h>
#interface ShopVC () <CBCentralManagerDelegate>
#property (nonatomic, strong) CBCentralManager *bluetoothManager;
#end
#implementation ShopVC
- (void)viewDidLoad {
[super viewDidLoad];
if(!self.bluetoothManager)
{
NSDictionary *options = #{CBCentralManagerOptionShowPowerAlertKey: #NO};
self.bluetoothManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:options];
}
}
#pragma mark - CBCentralManagerDelegate
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
NSString *stateString = nil;
switch(self.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."; break;
case CBCentralManagerStatePoweredOn: stateString = #"Bluetooth is currently powered on and available to use."; break;
default: stateString = #"State unknown, update imminent."; break;
}
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Bluetooth state"
message:stateString
delegate:nil
cancelButtonTitle:#"ok" otherButtonTitles: nil];
[alert show];
}

Related

Checking if Bluetooth is Disabled on iOS 5 without BluetoothManager

I have seen that in iOS 5, CoreBluetooth provides the capability to check if Bluetooth is disabled. From what I have seen of the documentation, it is clearly aimed at bluetooth peripheral use. However, I am attempting to check if bluetooth is on because I am using GameKit (GKPeerPickerController) that will search endlessly for bluetooth connections if it is not enabled, which is an issue.
I tried to do this like so:
CBCentralManager * manager = [[CBCentralManager alloc] init];
if (manager.state == CBCentralManagerStatePoweredOn ) {
//go ahead with GameKit
}
This does not work, and manager.state is always equal to null. What am I doing wrong here? Or alternatively, are there better ways to check the status of bluetooth on the iPhone?
EDIT: I don't want to call any private APIs because I will be submitting this app to the app store. I have edited my question title to clarify this.
Ok, I discovered that by doing this:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
NSMutableArray * discoveredPeripherals = [NSMutableArray new];
CBCentralManager * manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[manager scanForPeripheralsWithServices:discoveredPeripherals options:options];
[manager stopScan];
If bluetooth is off, the system will pop up an alert view which will offer the choice to turn bluetooth on. Otherwise, if it finds a peripheral it will call a corresponding delegate method, but if there is nothing in that implementation you don't need to worry about it.
You can find the answer of your question by this link. Check it out.
Edited
Have you checked out the Game Kit Framework reference?
According to Apple:
Game Kit offers your applications the ability to create Bluetooth
connections between two devices.
Edited
Then try this project. https://github.com/sergiomtzlosa/MultiContactsSelector-ios

iOS 5: programmatically turn bluetooth on and off

I saw that programmatically turning bluetooth on and off was a "private api" thing in previos versions of iOS that would get an app rejected from the apple itunes store.
But in iOS 5, I am aware of previously private things that are no longer private, such as programmatically changing screen brightness. Doing this will no longer get your app rejected in itunes with iOS 5, so I am wondering if this other things were available publicly, like the bluetooth adapter.
CoreBluetooth is publicly available in iOS 5. Unfortunately it only works for new Bluetooth LE (Low Energy) devices.
See CoreBluetooth Documentation
This is not public. You will get rejected.
According to the iOS 5.0 Release Notes there is no mention of any Bluetooth functionality being publicly available.
I needed to enable bluetooth programmatically. What I did was use the GKPeerPickerController, this asks you to enable bluetooth if it's not already on. Then on a call for the GKPeerPickerControllerDelegate I dismiss the picker.
Not perfect, you will see the "Searching for devices" for a short time, but It works in lack of another way of doing this (as far as I know).
GKPeerPickerController * peerpicker = [[GKPeerPickerController alloc]init];
peerpicker.delegate = self;
peerpicker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
[peerpicker show];
When the peerpicker is ready to search there's a delegate method to return a GKSession for the picker to use. This is where you dismiss it.
-(GKSession*)peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type
{
[picker dismiss];
[picker autorelease];
return nil;
}
And your app won't get rejected.
No, bluetooth is still not available :(

getting operator details in iphone

How to get the currently using operator details (like Airtel or Idea or etc..)of iPhone.
Is it possible to get those details or is there any way to identify which operator currently we are using.I am developing an application which is based on the operator, if user changes his SIM(Operator) then the app shouldn't work, it has to work for that particular operator.
CTCarrier should have the info you need in it.
Edit: CTTelephonyNetworkInfo responds to a user switching SIMs mid-session, and provides an instance of CTCarrier for you.
Sample code (in your app delegate):
#import <CoreTelephony/CoreTelephony.h>
static NSString *requiredCarrier = #"Verizon"; // example carrier
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CTTelephonyNetworkInfo *myNetworkInfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *myCarrier = [myNetworkInfo subscriberCellularProvider];
if(![[myCarrier carrierName] isEqualToString:requiredCarrier])
{
// lock the app, possibly terminate the app after displaying a UIAlertView
// informing the user of the network-lock.
}
// ...
return YES;
}
Note the following advisory on the properties of CTCarrier (I would recommend not doing a permanent one-way lock if a nil carrier is read):
"The value for this property is nil if any of the following apply:
The device is in Airplane mode.
There is no SIM card in the device.
The device is outside of cellular service range."
Of the properties of CTCarrier to validate on, I would recommend carrierName specifically as it doesn't change when the user is roaming so the app will still work as long as the SIM is tied to your desired operator.
Just a quick note in case someone is looking for this.
I have noticed from playing with the CTCarrier API that "nil" is returned to any of its properties only on the emulator. On the device it returns #"" (blank string) for some reason! Checking agains nil failed ont eh device but checking equality with #"" worked!
You can use the Core Telephony framework to achieve this. In particular CTCarrier and the carrierName property. View the documentation here: http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Reference/CTCarrier/Reference/Reference.html%23//apple_ref/doc/uid/TP40009596

Matching an NSString with part of a text paragraph on a website. - iPhone SDK

So basically I'm working on an application, and one of the features is an anti-cracking feature. It checks the webpage for the UDID number of the device, and if it is there, it allows the application to run, if it's not there, it runs exit(0);. So far, this is what I have.
This is in my AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[window addSubview:mainViewController.view];
if ([[[UIDevice currentDevice] uniqueIdentifier] isEqualToString:[NSString stringWithContentsOfURL:[NSURL URLWithString:#"http://example.com" ]]]) {
NSLog(#"Match!");
[window makeKeyAndVisible];
}
else {
NSLog(#"No match.");
alertView = [[UIAlertView alloc] initWithTitle:#"Access denied!" message:#"You aren't using an official version of this application." delegate:self cancelButtonTitle:#"Okay" otherButtonTitles:nil];
[alertView show];
[alertView release];
}
return YES;
}
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
exit(0);
}
}
And so basically, where you see
if ([[[UIDevice currentDevice] uniqueIdentifier] isEqualToString:[NSString stringWithContentsOfURL:[NSURL URLWithString:#"http://example.com" ]]]) {
When it runs that, it can only detect all of the text, rather than indexing it and finding that UDID number. So I can only put 1 UDID number on there, therefore making every user's application crash. I want to set it up so that I can have as many things on there as I want, and it will just index it and search for that UDID number on the page. Can anybody help me please? It's very important!
Thank you very much!
Yay so if I buy your app and your server is down (stringWithContentsOfURL returns nil) your app wil think I pirated your software!
How about spending time on bug free end-user features instead of this?
I don't understand how this is supposed to be an "anti-cracking feature", unless you plan to somehow obtain the UDIDs of all the devices of a user who has legally purchased your app through iTunes. You can't get such a list. And even if you could, it might be a violation of Apple's developer agreement, especially the section on privacy and storage of information.
So in summary:
This solution is fundamentally and fatally flawed.
There are other anti-cracking techniques that will be more effective, especially those that use a softer approach... but none will be perfect.
As St3fan says, your technique requires a working Internet connection, which is not something you can always assume. In which case, this technique does not fail gracefully. In which case, Apple can reject your app. It will not be "[Apple's] problem" if it fails. It is your problem.
As for me, it would be easier to generate an xml of UDIDs, then parse it into an array and then compare each element with paticular UDID

GKSession - what if I have Bluetooth and Wi-Fi turned off?

I'm working on an iPhone app that will allow for peer-to-peer connections. From what I understand, I have the choice between using GKPeerPicker or the GKSession. I don't like the idea of using the PeerPicker because I want to show a custom interface, so I decided to go with GKSession, and hey, BONUS is that it also works over Wi-Fi, whereas the Peer Picker does not.
OK, so problem is... what if the user has both Bluetooth and Wi-Fi turned off? In the Peer Picker, there is a prompt to turn Bluetooth on w/o leaving the app. GKSession doesn't have it... but woah wait a second, it appears that I can't even check to see if Bluetooth is on or not programatically!
Carpe Cocoa claims no problem, just use the Delegate's session:didFailWithError: method. But, as it explains in the comments... that doesn't seem to work anymore! And in my experience, I concur.
Is there some other way to programmatically check if Bluetooth is on? Is this something that I should be leveraging Reachability for? Or is it just a bug that Apple has yet to fix?
To be more specific, I'm creating my session like this:
GKSession *aSession = [[GKSession alloc] initWithSessionID:nil
displayName:user.displayName
sessionMode:GKSessionModePeer];
self.gkSession = aSession;
[aSession release];
self.gkSession.delegate = self;
self.gkSession.available = YES;
[self.gkSession setDataReceiveHandler:self withContext:NULL];
The class implements the GKSessionDelegate, and I know that it's working because when I have bluetooth turned on, the delegate methods are called no problem. I've implemented them as such:
#pragma mark -
#pragma mark GKSessionDelegate methods
- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state {
if (GKPeerStateAvailable == state) {
[session connectToPeer:peerID withTimeout:10];
} else if (GKPeerStateConnected == state) {
// gets user
NSError *error = nil;
[session sendData:user.connectionData
toPeers:[NSArray arrayWithObjects:peerID,nil]
withDataMode:GKSendDataReliable error:&error];
if (error)
NSLog(#"%#",error);
}
}
- (void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID {
NSError *error = nil;
[session acceptConnectionFromPeer:peerID error:&error];
if (error)
NSLog(#"%#",error);
}
- (void)session:(GKSession *)session connectionWithPeerFailed:(NSString *)peerID withError:(NSError *)error {
NSLog(#"%#",error);
}
- (void)session:(GKSession *)session didFailWithError:(NSError *)error {
NSLog(#"%#",error);
}
None of the log statements are printed and I set breakpoints in each method, but none of them are hit when the user has both Bluetooth and Wi-Fi turned off. I was hoping that something would happen to trigger session:didFailWithError: so that I could prompt the user to turn on Bluetooth or connect to a Wi-Fi network.
Now in iOS 5, this can be achieved like so:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], CBCentralManagerScanOptionAllowDuplicatesKey, nil];
NSMutableArray * discoveredPeripherals = [NSMutableArray new];
CBCentralManager * manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
[manager scanForPeripheralsWithServices:discoveredPeripherals options:options];
[manager stopScan];
This requires that you import the CoreBluetooth framework in iOS 5. If bluetooth is off, the system will pop up an alert view which will offer the choice to turn bluetooth on. Otherwise, if it finds a peripheral it will call a corresponding delegate method, but if there is nothing in that implementation you don't need to worry about it.
I agree with Martin Gordon, but a workaround might be to use Apple's reachability.
Interesting point, have you tried testing it with Bluetooth OFF and the WiFi ON? I found out recently that although my program was calling this 'Bluetooth Unavailable' message, it wasn't in fact using Bluetooth AT ALL but was connecting over my WiFi network. I don't know of a way to force GKSession into a Bluetooth connection without using Apple's PeerPicker object, but the PeerPicker object does allow for people to make their own interfaces. What it doesn't seem to allow is connection types other than Peer, so if you want a Client/Server arrangement it's not going to be much help.
-Ash
You can switch on Blutooth programmatically, by using Apple's private API (i think BluetoothManger.h), but be careful , it will cause rejection in the Apple App Store push.
I second the notion of using Apple's reachability. As a bonus it's listed as one of the Apple App Store submission guidelines.
It's not that hard to implement either as much of the code needed is already written for you.
Slf provided a link to some source code using the Reachability class, additionally here's a link to Apple Dev's official reachability example.
However, make sure you are checking for connectability asynchronously.
I'm using it in my app and although it isn't the best solution at least it notifies the user that he/she needs to adjust the connection settings or that no networks exist.
You should use the same sessionID.