Core Bluetooth: Cannot get iPhone (the central) and Mac (the peripheral) to pair - iphone

I am developing an iPhone application and a Mac application that communicate with each other via Bluetooth LE. The iPhone is the central, and the Mac is the peripheral. I would like the iPhone application to be able to reconnect to the Mac application after a relaunch. Therefore, I save the UUID of the peripheral representing the Mac in NSUserDefaults, and then when the iPhone app launches, I call -[CBCentralManager retrievePeripheralsWithIdentifiers:], passing in the UUID. Although this method returns the peripheral, when I call -[CBCentralManager connectPeripheral:options:], the iPhone never reconnects to the Mac. According to this SO post, the problem is that the two devices need to be paired so that the UUID of the Mac is persistent. This brings me to my problem. I cannot for the life of me get the iPhone and the Mac to pair. According to this page of the Core Bluetooth Programming Guide, the way to require a paired connection is for the peripheral to set the characteristic's properties and permissions to the appropriate values. I quote:
You can ensure that only trusted devices have access to sensitive characteristic values by setting the appropriate characteristic properties and permissions. To continue the example above, to allow only trusted devices to retrieve a member’s email address, set the appropriate characteristic’s properties and permissions, like this:
emailCharacteristic = [[CBMutableCharacteristic alloc]
initWithType:emailCharacteristicUUID
properties:CBCharacteristicPropertyRead
| CBCharacteristicPropertyNotifyEncryptionRequired
value:nil permissions:CBAttributePermissionsReadEncryptionRequired];
However, this does not work. Even when I set the correct permissions and properties for the characteristic, the iPhone can still read/write to it without a pairing dialog being displayed. Elsewhere I am told that the way to initiate pairing is for the peripheral to reject a read/write request with an insufficient authentication error. According to this post,
To pair, you need to respond to a write request with an insufficient authentication error. For example, for an iOS peripheral you would write something like:
- (void)peripheralManager:(CBPeripheralManager *)peripheralManager didReceiveWriteRequests:(NSArray *)requests {
...
[peripheralManager respondToRequest:request withResult:CBATTErrorInsufficientAuthentication];
...
}
But this still doesn't work! When the Mac rejects the write request with an insufficient authentication error, the iPhone receives a -[CBPeripheralDelegate peripheral:didWriteValueForCharacteristic:error:] callback with an error that says, "Authentication is insufficient." No pairing dialog. I have no idea what to do and am considering dropping Core Bluetooth altogether if I cannot get this to work. If you have any idea how to get this to work, please let me know.

From Apple DTS:
"I have checked with other engineers here and we don’t believe that the pairing popup is possible between two iOS devices, but an iOS device and a BLE peripheral."
So, pairing popup happens only between a iOS/Mac app and a peripheral. rdar time.

Related

External Device reports no Protocol

I have an app that I have been working on and I am now at the point that I want to integrate some interaction with an external device via the dock connector. The device that I am using (the iDive 300) conforms to the Made For iPod program. I have written a separate simple app based on the EADemo code to gather information about the device. However, when I run this app the iDive reports nothing for the Name, Serial Number, Firmware, etc and also says that no protocols were found. I know this simple app is working correctly because I have connected to several other external devices and the Name, serial number, etc is populated for each device.
The other odd thing is that the iDive seems to work properly when plugged into my iPhone 4 (i.e. it will increase the volume and play songs and videos found on my iPhone via the buttons on the device). Shouldn't this mean that some protocol is in place for this device to communicate with the iPhone? Is it all possible for me to read data from this device (e.g. capture when the 'play','menu', or other buttons are pressed) if I don't know the protocol?
I am completely new to the External Accessories framework and any help is appreciated!
You should autopsy the app that is associated with iDive. In its info.plist, there should be a key:
UISupportedExternalAccessoryProtocols
whose value is an array(See this for the formal definition), and within it lies a string whose value looks like a reversed domain name, as the device protocol.
You should edit your Info.plist, add the key('Supported external accessory protocols' in plain English) for an array, put in the protocol as its item.
There's no guarantee that an accessory actually uses EA. It may communicate using the protocols defined by Apple.
EA is only necessary if you want to communicate using your own proprietary protocol.
Check the EADemo example from Apple... If it doesn't show up in the demo app, it's not EA.

Check device is locked?

I've a multitasking application and I'm using all the app delegate events for backgrounding but when the device locked or idle timer expires none of the delegate events get fired. So I need to check device lock status.
Is there way to do this with SDK(non private api solution)?
Maybe you can watch after an item in the Keychain :
kSecAttrAccessibleWhenUnlocked
The data in the keychain item can be accessed only while the device is unlocked by the user. This is recommended for items that need to be accesible only while the application is in the foreground. Items with this attribute migrate to a new device when using encrypted backups.
Available in iOS 4.0 and later.
Declared in SecItem.h.
From : http://developer.apple.com/library/ios/#documentation/Security/Reference/keychainservices/Reference/reference.html
From the discussion it sounds like you could use applicationProtectedDataWillBecomeUnavailable:
On a device that uses content protection, protected files are stored in an encrypted form and made available only while the device is unlocked. This notification lets your application know that the device is about to be locked and that any protected files it is currently accessing will be unavailable shortly.
If your application is currently accessing a protected file, you can use this method to release any references to that file. Although it is not an error to access the file while the device is locked, any attempts to do so will fail. Therefore, if your application depends on the file, you might want to take steps to avoid using that file while the device is locked.
I assume this will get called regardless of whether or not you are using protected files. I have not tested it yet though.

Store value of AlertView in iphone

HI,
I'm aware that accessing the SMS incoming isn't possible in the iPhone SDk but could i read the alertView that is active on the iPhone (ie. new SMS alert) and store its values into a variable? Obviously this would require backgrounding but in theory could this work?
As other stated, you cannot see the SMS message or associated alerts.
Not sure about iOS, but on other platforms (e.g. Java ME) it is possible to address an SMS to your application instead of the phone's "inbox" (default handler). This requires that you control the server sending the SMS message.
I imagine even if you could catch an SMS targeted at your iOS app, you wouldn't. Instead use Apple's Push Notification system.
I hesitate to type this in an iOS related question, but the Android OS makes it pretty trivial for an app to see SMS messages. You can even be woken up as they arrive. So, if you just want to test out some idea you have, consider that.
No. You can access your own alerts but not those from other applications.
Unfortunately, you cannot access other application's data, be it in background or not.

What are the APIs used by MobileMe's Find My iPhone?

How does Apple do polling of a phone's location remotely? Is there any API that allows an app developer to do the same with the SDK?
My guess is that they are private, undocumented and probably un-callable api's.
I couldn't imagine the huge security implications of having an external party/app be about to poll a phone location without the users consent.
An iOS device already maintains a connection to one of Apple's push servers if push is enabled, and the server has to know the device on the end of the connection (to determine the push notifications to deliver to it). The easiest way to build on this is to have the server say "tell me where you are!" as a push notification.
The device also hits Apple's servers for other reasons (App Store updates, captive login page detection), but it's less likely that the server can identify the device in these cases.
That said, you can do this with the user's consent:
Make your app a background "voip" app (<key>UIBackgroundModes</key><array><string>voip</string></array> I think)
At app launch, check that you can retrieve the current location (I'm not sure what happens if you do this while your app is backgrounded).
Maintain a "voip" connection to your server.
When the server asks the device for its location, ask Core Location for the location again and send it to the server. (I think you also need either "location" in UIBackgroundModes or you need to keep the connection active, possibly in both directions; the former may be easier.)
You won't be able to stop the "location services" icon from appearing in the status bar. The usual multitasking caveats also apply (your app can be killed if the phone runs out of memory; "voip" causes your app to be relaunched sometime later though).
I'm pretty sure if you do the "voip trick" your app will be refused from the store. It is only allowed if your app is actually a VOIP app, not just using it as a technique to circumvent background processing restrictions.

Apple Push Notifications - When Registering for Notifications no Callbacks are received at all

I've gone through all the steps as specified, am using a dev certificate with APN enabled and am calling registerForRemoteNotificationTypes: with the right flags in my app delegate.
Still, neither application:didRegisterForRemoteNotificationsWithDeviceToken: nor application:didFailToRegisterForRemoteNotificationsWithError: are being called. It looks like the registration request just gets stuck in transit.
What am I doing wrong?
This sounds silly, but it's bit me in the past: double-check your capitalization and parameter types. If a delegate method declaration isn't spot on your method won't get called, and you won't get any kind of warning.
Your best bet is to copy and paste the prototype from Apple's documentation.
Try your App on another device. If it works there...
I have the same Problem with one iPhone 3G (no jailbreak, no unlock). It somply dos not work with that phone. I tried updating to a newer iPhone OS. I tried a factory reset. It does show the confirmationscreen and it records the answer in the Settings. But neither application:didFailToRegisterForRemoteNotificationsWithError nor application:didRegisterForRemoteNotificationsWithDeviceToken are ever called.
The same App works on all other tested devices (ipods, iphones). This iPhone 3G does also not receive PNs for other apps.
PNs also did not work for one Jailbroken Classic iPhone.
It might be that your device is simply not behaving correctly. Try a different device.
I had this problem too and it was because of bad certificates, app id, provision profile...
Make sure that:
1, Correct certificates are installed on client AND server
2, Make sure that you have selected correct provision profile in your project settings. REMEMBER App ID in your provision profile has to be specific(not ending with *) and last part of this App ID has to match name of your application exactly and it is case sensitive. so iv your app is called myApp then your app id has to be SOMENUMBERScom.yourcompany.myApp
Just an idea...
I had the same problem and solved it by disconnecting from the cellular network. Seems to be some problem when both wireless and 3G are on concurrently.
I found out that PUSH notifications require port 5223 open in your network (if you are using WIFI), or otherwise, a cellular data connection.
I encountered the same problem in my home network, and had to open the port manually in the wireless router.