pebble
  • Tutorials
  • Get the SDK
  • Guides
  • Documentation
  • Examples
  • Community
  • Blog
  • More
Privacy
Cookies
Publish
Get Updates
Follow Us
Subscribe to the Newsletter

Creating Native Companion Apps with JS and Cordova

  • 01 July 2016
  • Ryan Perry-Nguyen
  • Freshly Baked
  • Comments

Creating companion apps using PebbleKit Android and PebbleKit iOS is a great way to extend the functionality of your Pebble watchfaces and apps, but what if Java or Objective C just isn't your thing? What if you love JavaScript? What if you just don't want to write the same companion app twice?

Now you don't have to! Enter Cordova - an open source framework for building cross-platform mobile apps using web technologies such as HTML5 and JavaScript. What does this mean for you? One framework, and one codebase for building Pebble companion apps for iOS and Android!

Cordova allows developers to create plugins that wrap native functionality such as accessing the phone's contacts, calendar, camera, and other phone APIs. Plugins allow you to interface with these APIs through JavaScript, and use them in your Cordova projects. Needless to say, PebbleKit Android and PebbleKit iOS are now available as a singular Cordova plugin.

In this blog post, we'll look at how to use Cordova to create a companion app that allows you to retrieve the next upcoming calendar event for the current day.

Setup

The first step will be installing Cordova and creating a new project. Cordova provides these steps generically here, but if you want to follow along down to the T, here are the steps listed below.

$ npm install -g cordova
$ cordova create calendar-example com.pebble.calendarexample "Calendar Example"
$ cd calendar-example
$ cordova platform add android
$ cordova platform add ios
$ cordova plugin add cordova-plugin-calendar
$ cordova plugin add cordova-plugin-pebblekit

Note, this assumes you have node/npm already installed and avaiable on your machine. If not, head on over to nodejs.org to install node.

Doesn't seem too bad! If the cordova create command seems a little scary to you, don't be afraid to ask for help with cordova create --help.

Querying Events

The next step is to use the calendar plugin we added earlier in order to fetch the next event for the day. Before we do that though, we'll need to to setup the Cordova PebbleKit plugin, as shown below. Fire up your favourite text editor and open www/js/index.js file. This is the JavaScript file that runs when your app starts up, your application's control logic will go here.

Upon opening the file, you'll notice there's already a fair bit of code generated by Cordova. What's important here is the onDeviceReady function, this is a callback you can use to be notified once the plugins for your Cordova project have been loaded and are ready to be called. Let's create our own function called fetchCalendarEvent to be called once the PebbleKit plugin has been setup. We'll also declare a variable uuid with our Pebble app's UUID, which is required when communicating with our watchapp via AppMessage.

var uuid = "ebc92429-483e-4b91-b5f2-ead22e7e002d";
var app = {

  /* ... */

  onDeviceReady: function () {
    app.receivedEvent('deviceready');
    window.pebblekit.setup(uuid, function () {
      app.fetchCalendarEvent();
    });
  },

  fetchCalendarEvent: function () {
    var startDate = new Date(); // Now
    var endDate = new Date();
    endDate.setHours(24, 0, 0, 0); // Nearest midnight in the future

    window.plugins.calendar.findEvent(
      undefined, // title
      undefined, // eventLocation
      undefined, // notes
      startDate,
      endDate,
      app.calendarSuccessCallback,
      app.calendarFailureCallback
    );
  },

  calendarSuccessCallback: function (events) {
    // TODO
  },

  calendarFailureCallback: function (err) {
    console.error('Failed to fatch calendar events', err);
  }

  /* ... */

}

Note, the calendar plugin recommends checking that you have sufficient permissions before using its APIs. For the sake of brevity, the permission workflow has been omitted in this post.

The first 3 parameters we passed to the calendar.findEvent function are undefined, since we don't want to filter out events with specific titles, locations, or notes. The last two parameters are callback functions that will be executed when the app has succeeded or failed to fetch calendar data. Our calendarFailureCallback will log a simple message, and our calendarSuccessCallback will sort through the events and find the earliest event in the list.

calendarSuccessCallback: function (events) {
  if (events.length == 0) {
    // TODO
    return;
  }

  // Find the earliest returned event
  var earliestEvent = events[0];
  for (var i = 1; i < events.length; i++) {
    var tempDate = events[i];
    var date1 = Date.parse(earliestEvent.startDate);
    var date2 = Date.parse(tempDate.startDate);

    if (date2 < date1) {
      earliestEvent = tempDate;
    }
  }
},

Sending An AppMessage

All we have to do now is send the relevent bits of information down to our Pebble app. This is where the Pebble plugin is going to come in handy. At the end of the function, we'll call sendAppMessage which works in a similar manner to PebbleKit JS' sendAppMessage function.

The title is easy to snag - it's a property on the event object, available via event.title. The hours and minutes will take a bit of work since they only exist within a string property on the object (event.startDate). Luckily the format for the date is fixed, so we know where in the string it will be.

With this in mind, we can use the String.prototype.substring method to extract the numbers we want. The method takes two parameters, the first is the starting index (inclusive) of the substring, and the second is the the end index (exclusive). So if we want the hour, we'd pass 11 as the starting index, and 13 as the end index. This will create a substring containing the 11th and 12th characters of the string.

Also in this example, the data object represents our AppMessage, where 10, 11, and 12 are the AppMessage keys.

// Format is in YYYY-MM-DD HH:mm:ss
var hourString = earliestEvent.startDate.substring(11, 13);
var hour = parseInt(hourString);
var minuteString = earliestEvent.startDate.substring(14, 16);
var minute = parseInt(minuteString);

// AppMessage keys
var data = {
  '10': earliestEvent.title,
  '11': hour,
  '12': minute
};

window.pebblekit.sendAppMessage(uuid, data, function () {
  console.log('sent AppMessage', data);
}, function (err) {
  console.error('Couldn\'t send AppMessage', err);
});

The only thing left is to read the AppMessage on the C side. To quote every university professor I've ever had: "We leave this as an exercise to the reader". (Just kidding, you can see the watchface's full C code here, or consult the documentation).

While we only used two of the APIs of the PebbleKit Cordova plugin here, there is much more available to you, all with new and shiny documentation

For folks that are interested, our Cordova plugin is completely open source, and hosted on Github. We welcome bug reports, feature requests, and contributions with open arms :).

And that's all there is to it! If you've been holding back on writing a companion app for your amazing app, now's the time to try it!


You need JavaScript enabled to read and post comments.
Get Updates
Follow Us
Subscribe to the Newsletter

Overview

  • Setup
  • Querying Events
  • Sending An AppMessage

Categories

  • All Posts
  • #makeawesomehappen
  • At the Pub
  • Beautiful Code
  • CloudPebble
  • Down the Rabbit Hole
  • Freshly Baked
  • Timeline

Authors

  • Thomas Sarlandie
  • Niharika Bedekar
  • Katharine Berry
  • Jon Barlow
  • Cherie Williams
  • Chris Lewis
  • Team Pebble
  • Katherine McAuliffe
  • Cat Haines
  • Alex Lin
  • Kirby Kohlmorgen
  • Brad Murray
  • Alexey Komissarouk
  • Ɓukasz Zalewski
  • Tom Maremaa
  • Ryan Case
  • Ryan Perry-Nguyen
  • Keegan Lillo
  • Meiguro

Subscribe to the Pebble Developers Newsletter