Getting list of bluetooth devices nearby on iphone sdk - iphone

I need to be able to search for all bluetooth devices nearby and just get there ids. I don't need to pair at all. I am using iphone 2.3 beta.
Is this possible l have tried using GameKit and no luck does anyone know how to do this.
BOOL result = NO;
if (!session) {
session = [[GKSession alloc] initWithSessionID:#"SCANNER"
displayName:nil
sessionMode:GKSessionModePeer];
self.session.delegate = self;
[self.session setDataReceiveHandler:self withContext:nil];
self.session.available = YES;
result = YES;
}
it dies on [self.session setDataReceiveHandler:self withContext:nil];
with the following error
Scanner[42754:207] Error: 30500 -- Invalid parameter for -setDataReceiveHandler:withContext:.
then
~ DNSServiceRegister callback: Ref=471fa40, Flags=2, ErrorType=0 name=00rusor1A..iPhone Simulator regtype=_q1eu29voete9jf._udp. domain=local.

Does self implement the required method
- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context;
somewhere? Otherwise, it is unable to satisfy the needs of the -setDataReceiveHandler:withContext: method. Also, I don't believe you can access Bluetooth functions from within the iPhone Simulator.
Overall, I don't think this will do what you want. GameKit uses Bonjour discovery to detect other iPhones / iPod touches running similar game sessions within a local Bluetooth network. It will not detect all Bluetooth devices in the vicinity. You can use lower-level Bonjour discovery yourself to find all Bonjour devices that are network-accessible via WiFi or Bluetooth, but Bluetooth access itself is abstracted away from you.

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

Check if Bluetooth is Enabled?

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

MKMapView userLocation not showing in ipod

i used
self.mapView.showsUserLocation = YES;
for showing blue dot (circle) on MKmapview. Its working fine in simulator. but when i tested in Ipod, its not showing. Anybody know what will be the reason ? thanks in advance
If the blue circle doesn't show in Maps either, than your local wifi networks aren't in the system (on the iPod your locationis determined by the nearest wifi ssid's). Two solutions: get them listed (not sure where you can do that) or go somewhere where it does work. In the iPhone Simulator you get a simulated location, so not so interesting that it works.
If you get the blue circle in Maps but not in your map, we can look further at it.
Is the iPod on the same, wireless network with location services enabled?
Check if u have given the delegates --->map.delegate=SomeController;
-(void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark;
and
- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error;

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.

How to determine whether user is on Edge or 3G on iPhone

Though it is relatively straightforward to determine if an iPhone is on Wifi or a data network programmatically in your application, I can't figure out a way to determine if the iPhone is on Edge or 3G.
Anybody figure out a way to determine this?
Note: Not worried about Apple AppStore acceptance policies so I don't mind doing something hacky in my app. (The iPhones should not have to be jailbroken though)
The iPhone doesn't provide this kind of information to developers programmatically. The best you can hope for is to determine whether a connection to a given host will have to be routed over a cell network - see the SCNetworkReachability reference and the Reachability project for more.
Assuming the answer by Tim is right, one way you can tell if the user is on 3G or edge is you can test the speed of the connection by starting a timer having the app download some file from the web and calculate the speed, you should be able to tell if they are on 3G or Edge by the diffrence in speeds.
Try checking it from the status bar:
UIApplication *app = [UIApplication sharedApplication];
NSArray *subviews = [[[app valueForKey:#"statusBar"] valueForKey:#"foregroundView"] subviews];
NSNumber *dataNetworkItemView = nil;
for (id subview in subviews) {
if([subview isKindOfClass:[NSClassFromString(#"UIStatusBarDataNetworkItemView") class]]) {
dataNetworkItemView = subview;
break;
}
}
int connectivity;
connectivity = [dataNetworkItemView valueForKey:#"dataNetworkType"];
And the value keys I've found so far:
0 = No wifi or cellular
1 = 2G and earlier? (not confirmed)
2 = 3G? (not yet confirmed)
3 = 4G
4 = LTE
5 = Wifi
one way you can detect iPhone 2G for sure is to look at the device name as reported by the OS
#import <sys/utsname.h>
+ (NSString *)deviceType {
struct utsname u;
uname(&u);
NSString *returnValue = [NSString stringWithFormat:#"%s", u.machine];
return returnValue;
}
the return value you are looking for is "iPhone1,1" to indicated iPhone 2G. combine this with the Reachability project to tell when they're on a cell network and you you have 1 avenue to guarantee that they are on an edge connection