Privacy Policy ยท Cookie Policy
  • Home
  • Tutorials
  • Get the SDK
  • Guides
  • Documentation
  • Examples
  • Community
  • Blog
  • More
  • Tutorials
  • Learn C Basics
  • Create a C Watchface
  • Create a JS Watchapp
  • Add More Features
  • Go Beyond
  • PebbleKit Android Tutorial
  • PebbleKit iOS Tutorial
  • Learn C Basics
  • Learning C for the Pebble SDK
  • A Simple C Program
  • Hello, Pebble!
  • More C Concepts
  • Create a C Watchface
  • Build Your Own Watchface
  • Customize Your Watchface
  • Adding Content From The Web
  • Create a JS Watchapp
  • Build A Watchapp with Pebble.js
  • Expanded Weather Forecasts
  • Adding More Details
  • Add More Features
  • Add a Date View
  • Add a Battery Meter
  • Add Connection Alerts
  • Go Beyond
  • Vector Animations
  • PebbleKit Android Tutorial
  • Integrating with Android
  • Controlling Apps From Pebble
  • Rock, Paper, Scissors with Pebble
  • PebbleKit iOS Tutorial
  • Integrating with iOS
  • Controlling Apps From Pebble
  • Rock, Paper, Scissors with Pebble
  • Guides
  • App Resources
  • Appstore Publishing
  • Best Practices
  • Communication
  • Debugging
  • Design and Interaction
  • Events and Services
  • Graphics and Animations
  • Migrating Older Apps
  • Pebble Packages
  • Pebble Timeline
  • Smartstraps
  • Tools and Resources
  • User Interfaces
  • App Resources
  • Animated Images
  • App Assets
  • Converting SVG to PDC
  • Fonts
  • Images
  • Pebble Draw Command File Format
  • Platform-specific Resources
  • Raw Data Files
  • System Fonts
  • Appstore Publishing
  • Appstore Analytics
  • Appstore Assets
  • Preparing a Submission
  • Publishing an App
  • iOS App Whitelisting
  • Best Practices
  • Building for Every Pebble
  • Conserving Battery Life
  • Modular App Architecture
  • Communication
  • Advanced Communication
  • Datalogging
  • Sending and Receiving Data
  • PebbleKit Android
  • PebbleKit iOS
  • PebbleKit JS
  • Sports API
  • Debugging
  • Common Runtime Errors
  • Common Syntax Errors
  • Debugging with App Logs
  • Debugging with GDB
  • Design and Interaction
  • Benefits of Design Guidelines
  • Core Experience Design
  • Example Implementations
  • Round App Design
  • One Click Actions
  • Recommended Guidelines and Patterns
  • Events and Services
  • Accelerometer
  • Background Worker
  • Buttons
  • Compass
  • Dictation
  • Event Services
  • Pebble Health
  • Persistent Storage
  • Wakeups
  • Graphics and Animations
  • Animations
  • Drawing Primitives, Images and Text
  • Framebuffer Graphics
  • Vector Graphics
  • Migrating Older Apps
  • SDK 3.x on Aplite Migration Guide
  • SDK 3.x Migration Guide
  • SDK 4.x Migration Guide
  • SDK 2.x Migration Guide
  • PebbleKit iOS 3.0 Migration Guide
  • Pebble Packages
  • Creating Pebble Packages
  • Using Pebble Packages
  • Pebble Timeline
  • Creating Pins
  • Service Architecture
  • Managing Subscriptions
  • Libraries for Pushing Pins
  • Public Web API
  • Smartstraps
  • Hardware Specification
  • Protocol Specification
  • Talking To Pebble
  • Talking To Smartstraps
  • Tools and Resources
  • App Metadata
  • CloudPebble
  • Color Picker Tool
  • Developer Connection
  • Hardware Information
  • Internationalization
  • Command Line Tool
  • User Interfaces
  • App Configuration
  • App Exit Reason
  • AppGlance C API
  • AppGlance in PebbleKit JS
  • AppGlance REST API
  • Layers
  • Round App UI
  • Unobstructed Area
  • Documentation
  • Pebble C
  • Pebble JavaScript API (beta)
  • PebbleKit JavaScript
  • PebbleKit iOS
  • PebbleKit Android
  • Pebble C
  • Pebble JavaScript API (beta)
  • PebbleKit JavaScript
  • PebbleKit iOS
  • PebbleKit Android
  • Community
  • Events
  • Online Communities
  • Example Apps
  • Tools
  • Libraries
  • Events
  • Developer Retreat 2014
  • Developer Retreat 2015
  • Example Apps
  • Hello
  • Caltrain
  • HeroBoard
  • Multi Timer
  • Resistor Time
  • Tools
  • App Message Bridge
  • Appstore Badge Generator
  • GPath.svg
  • pBuild Travis CI Build Tool
  • Sublime Text Plugin
  • Watchface Generator
  • Watch Status
  • Libraries
  • Color Selector
  • Custom Status Bar for Pebble
  • EffectLayer
  • GBitmap Colour Palette Manipulator
  • Java Pebble Timeline
  • JS Message Queue
  • Pebble Timeline API for DotNet (C#)
  • Pebble API PHP
  • PebbleTimeline API Ruby
  • PHPebbleTimeline
  • PinPusher
  • pypebbleapi
  • Simple Dithering Library
  • T3 Keyboard
  • ToastLayer Library
  • More
  • Examples
  • App Inspiration
  • Contact
  • Build Tools
pebble
  • Tutorials
  • Get the SDK
  • Guides
  • Documentation
  • Examples
  • Community
  • Blog
  • More
Privacy
Cookies
Publish

Guides

  • Table of Contents
  • App Resources
  • Appstore Publishing
  • Best Practices
  • Communication
  • Debugging
  • Design and Interaction
  • Events and Services
  • Graphics and Animations
  • Migrating Older Apps
  • Pebble Packages
  • Pebble Timeline
  • Rocky.js
  • Smartstraps
  • Tools and Resources
  • User Interfaces

App Configuration (manual setup)

This page contains some instructions that are different if you're using CloudPebble or if you're using the SDK locally on your computer.

Select whether you're using CloudPebble or the SDK below to show the relevant instructions!

CloudPebble

SDK

Showing instructions for CloudPebble. Not using CloudPebble?

Showing instructions for the SDK. Using CloudPebble?

This guide provides the steps to manually create an app configuration page. The preferred approach is to use Clay for Pebble instead.

Many watchfaces and apps in the Pebble appstore include the ability to customize their behavior or appearance through the use of a configuration page. This mechanism consists of an HTML form that passes the user's chosen configuration data to PebbleKit JS, which in turn relays it to the watchface or watchapp.

The HTML page created needs to be hosted online, so that it is accessible to users via the Pebble application. If you do not want to host your own HTML page, you should follow the Clay guide to create a local config page.

App configuration pages are powered by PebbleKit JS. To find out more about PebbleKit JS, read the guide.

Adding Configuration

For an app to be configurable, it must marked as 'configurable' in the app's package.json capabilities array. The presence of this value tells the mobile app to display a gear icon next to the app, allowing users to access the configuration page.

"capabilities": [ "configurable" ]

For an app to be configurable, it must include the 'configurable' item in 'Settings'. The presence of this value tells the mobile app to display the gear icon that is associated with the ability to launch the config page.

Choosing Key Values

Since the config page must transmit the user's preferred options to the watchapp, the first step is to decide upon the AppMessage keys defined in package.json that will be used to represent the chosen value for each option on the config page:

"messageKeys": [
  "BackgroundColor",
  "ForegroundColor",
  "SecondTick",
  "Animations"
]

Since the config page must transmit the user's preferred options to the watchapp, the first step is to decide upon the AppMessage keys defined in 'Settings' that will be used to represent each option on the config page. An example set is shown below:

  • BackgroundColor

  • ForegroundColor

  • SecondTick

  • Animations

These keys will automatically be available both in C on the watch and in PebbleKit JS on the phone.

Each of these keys will apply to the appropriate input element on the config page, with the user's chosen value transmitted to the watchapp's AppMessageInboxReceived handler once the page is submitted.

Showing the Config Page

Once an app is marked as configurable, the PebbleKit JS component must implement Pebble.openURL() in the showConfiguration event handler in index.js to present the developer's HTML page when the user wants to configure the app:

Pebble.addEventListener('showConfiguration', function() {
  var url = 'http://example.com/config.html';

  Pebble.openURL(url);
});

Creating the Config Page

The basic structure of an HTML config page begins with a template HTML file:

Note: This page will be plain and unstyled. CSS styling must be performed separately, and is not covered here.

<!DOCTYPE html>
<html>
  <head>
    <title>Example Configuration</title>
  </head>
  <body>
    <p>This is an example HTML forms configuration page.</p>
  </body>
</html>

The various UI elements the user will interact with to choose their preferences must be placed within the body tag, and will most likely take the form of HTML input elements. For example, a text input field for each of the example color options will look like the following:

<input id='background_color_input' type='text' value='#000000'>
  Background Color
</input>
<input id='foreground_color_input' type='text' value='#000000'>
  Foreground Color
</input>

Other components include checkboxes, such as the two shown below for each of the example boolean options:

<input id='second_tick_checkbox' type='checkbox'>
  Enable Second Ticks
</input>
<input id='animations_checkbox' type='checkbox'>
  Show Animations
</input>

The final element should be the 'Save' button, used to trigger the sending of the user's preferences back to PebbleKit JS.

<input id='submit_button' type='button' value='Save'>

Submitting Config Data

Once the 'Save' button is pressed, the values of all the input elements should be encoded and included in the return URL as shown below:

<script>
  // Get a handle to the button's HTML element
  var submitButton = document.getElementById('submit_button');

  // Add a 'click' listener
  submitButton.addEventListener('click', function() {
    // Get the config data from the UI elements
    var backgroundColor = document.getElementById('background_color_input');
    var foregroundColor = document.getElementById('foreground_color_input');
    var secondTickCheckbox = document.getElementById('second_tick_checkbox');
    var animationsCheckbox = document.getElementById('animations_checkbox');

    // Make a data object to be sent, coercing value types to integers
    var options = {
      'background_color': parseInt(backgroundColor.value, 16),
      'foreground_color': parseInt(foregroundColor.value, 16),
      'second_ticks': secondTickCheckbox.checked == 'true' ? 1 : 0,
      'animations': animationsCheckbox.checked == 'true' ? 1 : 0
    };

    // Determine the correct return URL (emulator vs real watch)
    function getQueryParam(variable, defaultValue) {
      var query = location.search.substring(1);
      var vars = query.split('&');
      for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split('=');
        if (pair[0] === variable) {
          return decodeURIComponent(pair[1]);
        }
      }
      return defaultValue || false;
    }
    var return_to = getQueryParam('return_to', 'pebblejs://close#');

    // Encode and send the data when the page closes
    document.location = return_to + encodeURIComponent(JSON.stringify(options));
  });
</script>

Note: Remember to use encodeURIComponent() and decodeURIComponent() to ensure the JSON data object is transmitted without error.

Hosting the Config Page

In order for users to access your configuration page, it needs to be hosted online somewhere. One potential free service to host your configuration page is Github Pages:

Github Pages allow you to host your HTML, CSS and JavaScript files and directly access them from a special branch within your Github repo. This also has the added advantage of encouraging the use of version control.

Relaying Data through PebbleKit JS

When the user submits the HTML form, the page will close and the result is passed to the webviewclosed event handler in the PebbleKit JS index.js file:

Pebble.addEventListener('webviewclosed', function(e) {
  // Decode the user's preferences
  var configData = JSON.parse(decodeURIComponent(e.response));
}

The data from the config page should be converted to the appropriate keys and value types expected by the watchapp, and sent via AppMessage:

// Send to the watchapp via AppMessage
var dict = {
  'BackgroundColor': configData.background_color,
  'ForegroundColor': configData.foreground_color,
  'SecondTick': configData.second_ticks,
  'Animations': configData.animations
};

// Send to the watchapp
Pebble.sendAppMessage(dict, function() {
  console.log('Config data sent successfully!');
}, function(e) {
  console.log('Error sending config data!');
});

Receiving Config Data

Once the watchapp has called app_message_open() and registered an AppMessageInboxReceived handler, that handler will be called once the data has arrived on the watch. This occurs once the user has pressed the submit button.

To obtain the example keys and values shown in this guide, simply look for and read the keys as Tuple objects using the DictionaryIterator provided:

static void inbox_received_handler(DictionaryIterator *iter, void *context) {
  // Read color preferences
  Tuple *bg_color_t = dict_find(iter, MESSAGE_KEY_BackgroundColor);
  if(bg_color_t) {
    GColor bg_color = GColorFromHEX(bg_color_t->value->int32);
  }

  Tuple *fg_color_t = dict_find(iter, MESSAGE_KEY_ForegroundColor);
  if(fg_color_t) {
    GColor fg_color = GColorFromHEX(fg_color_t->value->int32);
  }

  // Read boolean preferences
  Tuple *second_tick_t = dict_find(iter, MESSAGE_KEY_SecondTick);
  if(second_tick_t) {
    bool second_ticks = second_tick_t->value->int32 == 1;
  }

  Tuple *animations_t = dict_find(iter, MESSAGE_KEY_Animations);
  if(animations_t) {
    bool animations = animations_t->value->int32 == 1;
  }

  // App should now update to take the user's preferences into account
  reload_config();
}

Read the Communication guides for more information about using the AppMessage API.

If you're looking for a simpler option, we recommend using Clay for Pebble instead.

Overview

  • Adding Configuration
  • Choosing Key Values
  • Showing the Config Page
  • Creating the Config Page
  • Submitting Config Data
  • Hosting the Config Page
  • Relaying Data through PebbleKit JS
  • Receiving Config Data