Companion Guide
chevron down
 

Companion Guide

Overview

A companion can be used to enhance any Fitbit application by providing it with an additional JavaScript runtime environment which exists within the Fitbit mobile application. This additional runtime can utilize resources and sensors of the mobile device through the Companion API, which greatly extends the capabilities of applications.

These two runtime environments can communicate with each other via the Messaging API, or via the File Transfer API.

Common Use Cases

Fitbit applications are not required to have an associated companion, but it is essential if they need to perform any of the following tasks:

  • Communicate with Web APIs.

  • Download images or other resources from the internet.

  • Utilize the mobile device GPS sensor.

  • Persist data on the mobile device.

  • Perform functions whilst the device application is not active.

  • Utilize the Settings API

Life Cycle Events

When an application is launched by the user, its associated companion is simultaneously launched on the mobile device. The companion can also subscribe to events which allow it to be woken even if the application is not currently running.

The following events which form part of the Life Cycle API and Wake Interval API can be used to wake the companion, and also determine why the companion was launched.

NOTE: A companion may not always be actively running due to mobile phone battery optimization. Companions can be launched with a life-cycle launch reason, or they may be already running and the life-cycle event will be emitted.

Periodic Wake Interval

The onwakeinterval event is emitted if the companion has configured a periodic wakeInterval timer to launch after a specified number of milliseconds.

The wokenUp property is set to true if the companion was woken up by the wakeInterval periodic timer.

NOTE: wakeInterval is not currently implemented in the Fitbit OS Simulator.

Begin wakeInterval

To begin the wakeInterval timer, set the value to a number of milliseconds greater than 300,000 (5 minutes).

The interval value is a mere guidance to the mobile runtime, not a guarantee that the companion will be woken up.

NOTE: Use of this API requires the run_background permission.

import { me as companion } from "companion";

if (!companion.permissions.granted("run_background")) {
  console.warn("We're not allowed to access to run in the background!");
}

const MILLISECONDS_PER_MINUTE = 1000 * 60;

// Tell the Companion to wake after 30 minutes
companion.wakeInterval = 30 * MILLISECONDS_PER_MINUTE;

// Listen for the event
companion.addEventListener("wakeinterval", doThis);

// Event happens if the companion is launched and has been asleep
if (companion.launchReasons.wokenUp) {
  doThis();
}

function doThis() {
  console.log("Wake interval happened!");
}

Cancel wakeInterval

To cancel the wakeInterval timer, set the value to 0, null, or undefined.

import { me as companion } from "companion"

// Cancel the wakeInterval timer
companion.wakeInterval = undefined

Significant Location Changes

The onsignificantlocationchange event is emitted if the companion has indicated that it should be woken when the device has changed physical location. The distance deemed to be a significant change is 5 kilometers.

The monitorSignificantLocationChanges flag is used to activate and deactivate this behavior.

The locationChanged property is set and contains the latest Position coordinates received from the mobile device GPS.

NOTE: Use of this API requires the access_location and run_background permissions.

Start Location Monitoring

import { me as companion } from "companion";

if (
  !companion.permissions.granted("access_location") ||
  !companion.permissions.granted("run_background")
) {
  console.error("We're not allowed to access to GPS Position!");
}

// Monitor for significant changes in physical location
companion.monitorSignificantLocationChanges = true;

// Listen for the event
companion.addEventListener("significantlocationchange", doThis);

// Event happens if the companion is launched and has been asleep
if (companion.launchReasons.locationChanged) {
  doThis(companion.launchReasons.locationChanged.position);
}

function doThis(position) {
  console.log(`Significant location change! ${JSON.stringify(position)}`);
}

Stop Location Monitoring

import { me as companion } from "companion"

// Don't monitor for significant changes in physical location
companion.monitorSignificantLocationChanges = false

Peer Application Launched

The peerAppLaunched property is set to true if the peer application was launched on the device.

import { me as companion } from "companion";

// Listen for the event
companion.addEventListener("readystatechange", doThis);

// The Device application caused the Companion to start
if (companion.launchReasons.peerAppLaunched) {
  doThis();
}

function doThis() {
  console.log("Device application was launched!");
}

Settings Changed

The settingsChanged property is set to true if the companion was woken up because of changes to settingsStorage.

import { me as companion } from "companion";
import { settingsStorage } from "settings";

// Listen for the event
settingsStorage.addEventListener("change", doThis);

// The companion was started due to settings changes
if (companion.launchReasons.settingsChanged) {
  doThis();
}

function doThis() {
  // Do something when the companion is launched or already running
}

Best Practices

Here's a simple list of best practices to follow when using a companion with your application:

  1. Don't wake your companion too frequently. This will negatively affect the battery of the mobile device and potentially the Fitbit device too.

  2. Cancel the life cycle events if you no longer need them.

  3. Listen for the life cycle event, and check launchReason, both are used.

  4. Request permissions where neccessary.

Companions in Action

If you're interested in using a companion alongside your application, why not check out the Bay Area Rapid Transit (BART) example or review the Companion API Reference Documentation.