Multiple Devices Guide
chevron down
 

Multiple Devices Guide

Overview

When developing applications or clock faces using the Fitbit SDK, you are able to build for multiple device targets simultaneously. These Build Targets are any device capable of running Fitbit OS, such as Fitbit Ionic and Fitbit Versa.

Hardware Differentiators

In addition to the new form factor and hardware design of Versa, there are some specific hardware differences between Ionic and Versa that developers should be aware of when creating applications or clock faces:

  1. They have a different size and shape display. Ionic is 348x250, while Versa is 300x300.

  2. Versa does not have on-board GPS, only connected GPS. If your application relies upon the Device Geolocation API, you should consider adding your own fallback method using the coordinates from the Companion Geolocation API.

Each device may have different hardware specifications, so during the development process it's important to cater for these different requirements either in code, or by including different resource files.

The recommended approach when dealing with multiple devices is to detect the capabilities of a device, rather than coding for a specific device model name. This way devices which share the same capabilities will be able to share the same application logic or resources.

Resource Files

The build process in Fitbit Studio has been designed to generate an application for each selected Build Target within a single .fba file. During the build process, only the relevant resources are included for each target. The build targets are selected within the package.json file in your project.

The current build process uses the screen resolution as the method for determining the device capability when bundling the resource files.

Resources such as images, css, and gui files can all be targeted to specific devices by using the following file-naming convention:

/resources/filename~SCREEN-RESOLUTION.ext

During the build process, we only include the relevant resources for each platform.

We always try to use the resource with the highest specificity first, then fall back to the default filename. For example, if you included these two files in your project:

/resources/styles~300x300.css\
/resources/styles.css

The file styles~300x300.css would be used on Versa, and styles.css would be used as the default for other platforms.

From a referencing perspective, just refer to the base filename (e.g., styles.css) in your code or gui files. The files are renamed without the screen resolution during the build process.

<link rel="stylesheet" href="styles.css" />

You are not required to target resource files to specific devices, but it's a simple way of keeping your resource files uncluttered, or optimized for specific devices.

Code Detection

To perform device detection within your code files, the BasicDeviceInfo interface includes the screen width and height. You can access screen dimensions via the Device.Device API, or the Companion.Peer API.

In order to ensure our applications continue to work on Ionic devices running older firmware, you must define the default screen width and height as follows:

if (!device.screen) device.screen = { width: 348, height: 250 };

Device API

import { me as device } from "device";
if (!device.screen) device.screen = { width: 348, height: 250 };
console.log(`Dimensions: $‌{device.screen.width}x$‌{device.screen.height}`);

Companion API

import { device } from "peer";
if (!device.screen) device.screen = { width: 348, height: 250 };
console.log(`Dimensions: $‌{device.screen.width}x$‌{device.screen.height}`);

Settings API

If you want to provide settings based on the type of connected device, you would need to pass them from the Companion API to the Settings API using settingsStorage, as follows:

import { device } from "peer";
if (!device.screen) device.screen = { width: 348, height: 250 };
settingsStorage.setItem("screenWidth", device.screen.width);
settingsStorage.setItem("screenHeight", device.screen.height);
function mySettings(props) {
  let screenWidth = props.settingsStorage.getItem("screenWidth");
  let screenHeight = props.settingsStorage.getItem("screenHeight");
}