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
andrun_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:
Don't wake your companion too frequently. This will negatively affect the battery of the mobile device and potentially the Fitbit device too.
Cancel the life cycle events if you no longer need them.
Listen for the life cycle event, and check launchReason, both are used.
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.