10 KiB
title | description | guide_group | order |
---|---|---|---|
PebbleKit iOS | How to use PebbleKit to communicate with a watchapp on iOS. | communication | 3 |
PebbleKit iOS is an Objective-C framework that works with the Pebble SDK and can be embedded in any iOS application for iOS 7.1 and above. Using the classes and methods in this framework, an iOS app can find and exchange data with a Pebble watch.
This section assumes that the reader has a basic knowledge of Objective-C, Xcode as an IDE, and the delegate and block patterns.
PebbleKit iOS should be compatible if your app uses Swift. The framework itself is written in Objective-C to avoid the requirement of the Swift runtime in pure Objective-C apps, and to improve the backwards and forwards compatibility.
Setting Up PebbleKit iOS
If the project is using CocoaPods (which is the
recommended approach), just add pod 'PebbleKit'
to the Podfile
and execute
pod install
.
After installing PebbleKit iOS in the project, perform these final steps:
- If the iOS app needs to run in the background, you should update your target’s
“Capabilities” in Xcode. Enable “Background Modes” and select both “Uses
Bluetooth LE accessories” and “Acts as a Bluetooth LE accessory”. This should
add the keys
bluetooth-peripheral
(“App shares data using CoreBluetooth”) andbluetooth-central
(“App communicates using CoreBluetooth”) to your target’sInfo.plist
file. - If you are using Xcode 8 or greater (and recommended for previous versions),
you must also add the key
NSBluetoothPeripheralUsageDescription
(“Privacy - Bluetooth Peripheral Usage Description”) to yourInfo.plist
.
To add PebbleKit iOS manually, or some other alternatives follow the steps in the repository. The documentation might also include more information that might be useful. Read it carefully.
Targeting a Companion App
Before an iOS companion app can start communicating or exchange messages with a watchapp on Pebble, it needs to give PebbleKit a way to identify the watchapp. The UUID of your watchapp is used for this purpose.
Set the app UUID associated with the PBPebbleCentral instance. A simple way to
create a UUID in standard representation to NSUUID
is shown here:
// Set UUID of watchapp
NSUUID *myAppUUID =
[[NSUUID alloc] initWithUUIDString:@"226834ae-786e-4302-a52f-6e7efc9f990b"];
[PBPebbleCentral defaultCentral].appUUID = myAppUUID;
If you are trying to communicate with the built-in Sports or Golf apps, their
UUID are available as part of PebbleKit with PBSportsUUID
and
PBGolfUUID
. You must register those UUID if you intend to communicate with
those apps.
Becoming a Delegate
To communicate with a Pebble watch, the class must implement
PBPebbleCentralDelegate
:
@interface ViewController () <PBPebbleCentralDelegate>
The PBPebbleCentral
class should not be instantiated directly. Instead, always
use the singleton provided by [PBPebbleCentral defaultCentral]
. An example is
shown below, with the Golf app UUID:
central = [PBPebbleCentral defaultCentral];
central.appUUID = myAppUUID;
[central run];
Once this is done, set the class to be the delegate:
[PBPebbleCentral defaultCentral].delegate = self;
This delegate will get two callbacks: pebbleCentral:watchDidConnect:isNew:
and
pebbleCentral:watchDidDisconnect:
every time a Pebble connects or disconnects.
The app won't get connection callbacks if the Pebble is already connected when
the delegate is set.
Implement these to receive the associated connection/disconnection events:
- (void)pebbleCentral:(PBPebbleCentral *)central watchDidConnect:(PBWatch *)watch isNew:(BOOL)isNew {
NSLog(@"Pebble connected: %@", watch.name);
// Keep a reference to this watch
self.connectedWatch = watch;
}
- (void)pebbleCentral:(PBPebbleCentral *)central watchDidDisconnect:(PBWatch *)watch {
NSLog(@"Pebble disconnected: %@", watch.name);
// If this was the recently connected watch, forget it
if ([watch isEqual:self.connectedWatch]) {
self.connectedWatch = nil;
}
}
Initiating Bluetooth Communication
Once the iOS app is correctly set up to communicate with Pebble, the final step is to actually begin communication. No communication can take place until the following is called:
[[PBPebbleCentral defaultCentral] run];
Once this occurs, the user may be shown a dialog asking for confirmation that they want the app to communicate. This means the app should not call
run:
until the appropriate moment in the UI.
Sending Messages from iOS
Since iOS apps are built separately from their companion Pebble apps, there is
no way for the build system to automatically create matching app message keys.
You must therefore manually specify them in package.json
, like so:
{
"Temperature": 0,
"WindSpeed": 1,
"WindDirection": 2,
"RequestData": 3,
"LocationName": 4
}
These numeric values can then be used as app message keys in your iOS app.
Messages are constructed with the NSDictionary
class and sent to the C
watchapp or watchface by the PBPebbleCentralDelegate
when the
appMessagesPushUpdate:
function is invoked.
To send a message, prepare an NSDictionary
object with the data to be sent to
the C watchapp. Data items are added to the
NSDictionary
using key-value pairs of standard data types. An example containing a string and
an integer is shown below:
NSDictionary *update = @{ @(0):[NSNumber pb_numberWithUint8:42],
@(1):@"a string" };
Send this dictionary to the watchapp using appMessagesPushUpdate:
. The first
argument is the update dictionary to send and the second argument is a callback
block that will be invoked when the data has been acknowledged by the watch (or
if an error occurs).
[self.connectedWatch appMessagesPushUpdate:update onSent:^(PBWatch *watch, NSDictionary *update, NSError *error) {
if (!error) {
NSLog(@"Successfully sent message.");
} else {
NSLog(@"Error sending message: %@", error);
}
}];
Once delivered, this dictionary will be available in the C app via the
AppMessageInboxReceived
callback, as detailed in
{% guide_link communication/sending-and-receiving-data#inbox-received %}.
Receiving Messages on iOS
To receive messages from a watchapp, register a receive handler (a block)
with appMessagesAddReceiveUpdateHandler:
. This block will be invoked with two
parameters - a pointer to a PBWatch
object describing the Pebble that sent the
message and an NSDictionary
with the message received.
[self.connectedWatch appMessagesAddReceiveUpdateHandler:^BOOL(PBWatch *watch, NSDictionary *update) {
NSLog(@"Received message: %@", update);
// Send Ack to Pebble
return YES;
}];
Always return
YES
in the handler. This instructs PebbleKit to automatically send an ACK to Pebble, to avoid the message timing out.
Data can be read from the NSDictionary
by first testing for each key's
presence using a != nil
check, and reading the value if it is present:
NSNumber *key = @1;
// If the key is present in the received dictionary
if (update[key]) {
// Read the integer value
int value = [update[key] intValue];
}
Other Capabilities
In addition to sending and receiving messages, PebbleKit iOS also allows more intricate interactions with Pebble. See the PebbleKit iOS Documentation for more information. Some examples are shown below of what is possible:
-
Checking if the watch is connected using the
connected
property of aPBWatch
.BOOL isConnected = self.watch.connected;
-
Receiving
watchDidConnect
andwatchDidDisconnect
events through being aPBDataloggingServiceDelegate
.
Limitations of PebbleKit on iOS
The iOS platform imposes some restrictions on what apps can do with accessories. It also limits the capabilities of apps that are in the background. It is critical to understand these limitations when developing an app that relies on PebbleKit iOS.
On iOS, all communication between a mobile app and Pebble is managed through a communication session. This communication session is a protocol specific to iOS, with notable limitations that the reader should know and understand when developing an iOS companion app for Pebble.
Bluetooth Low Energy (BLE) Connections
For Pebble apps that communicate with Pebble in BLE mode, a session can be created for each app that requires one. This removes the 'one session only' restriction, but only for these BLE apps. Currently, there are several BLE only devices, such as Pebble Time Round, and Pebble 2, but all the devices using a firmware 3.8 or greater can use BLE to communicate with PebbleKit.
For BLE apps, the 'phone must launch' restriction is removed. The iOS companion app can be restarted by the watchapp if it stops working if user force-quits iOS app, or it crashes. Note that the app will not work after rebooting iOS device, which requires it be launched by the iPhone user once after boot.
Communication with firmware older than 3.0
PebbleKit iOS 3.1.1 is the last PebbleKit that supports communication with firmwares older than 3.0. PebbleKit iOS 4.0.0 can only communicate with Pebble devices with firmware newer than 3.0.
For newer devices like Pebble Time, Pebble Time Steel, Pebble Time Round, and Pebble 2 there should be no problem. For previous generation devices like Pebble and Pebble Steel it means that their users should upgrade their firmware to the latest firmware available for their devices using the new apps.
This change allows better compatibility and new features to be developed by 3rd parties.