dc.getWidth() and
dc.getHeight(),
then adapt the interface for rectangular cycling computers and round Garmin watches at runtime.
Garmin Connect IQ is much more useful than simply downloading watch faces from the Connect IQ Store. With the official SDK and Monkey C, you can build your own cycling, running, hiking or training Data Field and decide exactly which metrics appear on the screen.
For example, an Edge 1050 cycling dashboard might prioritize speed, power, cadence, heart rate and distance, while a fēnix or Forerunner running screen may work better with pace, heart rate, elapsed time, cadence and elevation.
The important part is that these devices do not all use the same display. The Edge 1050 has a large rectangular screen, many fēnix and Forerunner watches use circular displays, and devices such as the Venu X1 use a near-square rectangular AMOLED screen. Hard-coding one set of coordinates therefore makes a Connect IQ project unnecessarily difficult to maintain.
Garmin Edge 1050 vs fēnix vs Forerunner: Why One Layout Does Not Fit Every Device
Garmin currently supports a very large range of Connect IQ devices. Even among modern products, screen shape, screen resolution and display technology vary considerably.
| Device | Resolution | Shape | Display | Good Example |
|---|---|---|---|---|
| Edge 1050 | 480 × 800 | Rectangle | High Color LCD | Cycling power dashboard |
| fēnix 8 47 / 51 mm | 454 × 454 | Round | AMOLED | Running / multisport |
| fēnix 8 Solar 51 mm | 280 × 280 | Round | Memory-In-Pixel | Hiking / ultra endurance |
| Forerunner 970 | 454 × 454 | Round | AMOLED | Running pace dashboard |
| Venu X1 | 448 × 486 | Rectangle | AMOLED | Fitness / hiking dashboard |
What Can You Build with a Garmin Connect IQ Data Field?
A Data Field runs inside an activity profile and receives activity information from Garmin. This makes it particularly useful for sports where the standard Garmin pages do not show data in exactly the way you want.
| Activity | Useful Metrics | Typical Device |
|---|---|---|
| Road Cycling | Speed, power, cadence, heart rate, distance | Edge 1050 / Edge 850 |
| Gravel / MTB | Speed, elevation, total ascent, HR, elapsed time | Edge / fēnix |
| Running | Pace, HR, cadence, distance, timer | Forerunner / fēnix |
| Hiking | Altitude, ascent, distance, HR, battery | fēnix / Venu X1 |
| Indoor Training | Power, cadence, HR, elapsed time | Edge / Forerunner |
Install the Garmin Connect IQ SDK and Monkey C Development Environment
As of 2026, Garmin's current developer release is Connect IQ SDK 9.2.0. The simplest development environment is Visual Studio Code with Garmin's Monkey C extension.
- Install Garmin Connect IQ SDK Manager.
- Sign in with your Garmin account.
- Download the current Connect IQ SDK.
- Download the device packages you want to test.
- Install Visual Studio Code.
- Install Garmin's Monkey C extension.
- Install Java 11 or newer.
One common beginner mistake is searching for a “Monkey C Chrome extension.” Monkey C development is normally done through the Visual Studio Code extension, not a browser extension.
Create a Multi-Device Garmin Data Field Project
A simple project can use the following structure:
UniversalGarminField/
├─ manifest.xml
├─ monkey.jungle
├─ developer_key.der
├─ source/
│ ├─ UniversalFieldApp.mc
│ └─ UniversalFieldView.mc
└─ resources/
├─ strings/
│ └─ strings.xml
└─ drawables/
├─ drawables.xml
└─ launcher_icon.png
manifest.xml
Garmin's VS Code extension can add supported products automatically through Monkey C: Edit Products. That method is safer than manually typing dozens of device IDs.
For a small test project, your manifest can initially contain only a few target devices.
<?xml version="1.0"?>
<iq:manifest xmlns:iq="http://www.garmin.com/xml/connectiq" version="3">
<iq:application
id="0123456789abcdef0123456789abcdef"
type="datafield"
name="@Strings.AppName"
entry="UniversalFieldApp"
launcherIcon="@Drawables.LauncherIcon"
minApiLevel="4.2.0">
<iq:products>
<iq:product id="edge1050"/>
<iq:product id="fr970"/>
<iq:product id="venux1"/>
</iq:products>
<iq:languages>
<iq:language>eng</iq:language>
</iq:languages>
</iq:application>
</iq:manifest>
monkey.jungle
project.manifest = manifest.xml
UniversalFieldApp.mc
using Toybox.Application as Application;
class UniversalFieldApp extends Application.AppBase {
function initialize() {
AppBase.initialize();
}
function getInitialView() {
return [ new UniversalFieldView() ];
}
}
The Most Important Part: Build a Responsive Garmin Data Field
A custom Garmin Data Field should normally draw relative to the available width and height rather than assuming one fixed resolution.
This matters for two reasons. First, the physical screen size differs between an Edge 1050 and a fēnix watch. Second, Garmin may place the same Data Field inside a smaller two-field, three-field or four-field layout.
dc.getWidth()dc.getHeight()Avoid:
assuming every screen is always exactly 480 × 800 or 454 × 454.
UniversalFieldView.mc Example
using Toybox.Graphics as Graphics;
using Toybox.System as System;
using Toybox.WatchUi as WatchUi;
class UniversalFieldView extends WatchUi.DataField {
private var _speed = 0.0f;
private var _distance = 0.0f;
private var _heartRate = null;
private var _cadence = null;
private var _power = null;
private var _altitude = null;
private var _ascent = null;
private var _elapsed = 0;
function initialize() {
DataField.initialize();
}
function compute(info) {
if (info == null) {
return;
}
_speed =
(info.currentSpeed != null)
? info.currentSpeed * 3.6f
: 0.0f;
_distance =
(info.elapsedDistance != null)
? info.elapsedDistance / 1000.0f
: 0.0f;
_heartRate = info.currentHeartRate;
_cadence = info.currentCadence;
_power = info.currentPower;
_altitude = info.altitude;
_ascent = info.totalAscent;
_elapsed =
(info.elapsedTime != null)
? info.elapsedTime
: 0;
}
function onUpdate(dc) {
var w = dc.getWidth();
var h = dc.getHeight();
dc.setColor(
Graphics.COLOR_WHITE,
Graphics.COLOR_BLACK
);
dc.clear();
// Large Edge-style rectangular display
if (h > w * 1.35) {
drawEdgeLayout(dc, w, h);
// Round or near-square watches
} else {
drawWatchLayout(dc, w, h);
}
}
private function drawEdgeLayout(dc, w, h) {
var cx = w / 2;
dc.drawText(
cx,
h * 0.05,
Graphics.FONT_SMALL,
"SPEED",
Graphics.TEXT_JUSTIFY_CENTER
);
dc.drawText(
cx,
h * 0.10,
Graphics.FONT_LARGE,
_speed.format("%.1f"),
Graphics.TEXT_JUSTIFY_CENTER
);
dc.drawText(
cx,
h * 0.19,
Graphics.FONT_XTINY,
"km/h",
Graphics.TEXT_JUSTIFY_CENTER
);
var y = h * 0.32;
drawMetric(
dc,
w * 0.25,
y,
"POWER",
valueOrDash(_power),
"W"
);
drawMetric(
dc,
w * 0.75,
y,
"CADENCE",
valueOrDash(_cadence),
"rpm"
);
y = h * 0.53;
drawMetric(
dc,
w * 0.25,
y,
"HEART RATE",
valueOrDash(_heartRate),
"bpm"
);
drawMetric(
dc,
w * 0.75,
y,
"DISTANCE",
_distance.format("%.1f"),
"km"
);
y = h * 0.74;
drawMetric(
dc,
w * 0.25,
y,
"ASCENT",
valueOrDash(_ascent),
"m"
);
drawMetric(
dc,
w * 0.75,
y,
"TIME",
formatElapsed(_elapsed),
""
);
}
private function drawWatchLayout(dc, w, h) {
var cx = w / 2;
// Keep important values away from the curved edge
var top = h * 0.16;
dc.drawText(
cx,
top,
Graphics.FONT_XTINY,
"PACE / SPEED",
Graphics.TEXT_JUSTIFY_CENTER
);
dc.drawText(
cx,
top + h * 0.08,
Graphics.FONT_LARGE,
_speed.format("%.1f"),
Graphics.TEXT_JUSTIFY_CENTER
);
dc.drawText(
w * 0.32,
h * 0.53,
Graphics.FONT_SMALL,
valueOrDash(_heartRate),
Graphics.TEXT_JUSTIFY_CENTER
);
dc.drawText(
w * 0.68,
h * 0.53,
Graphics.FONT_SMALL,
valueOrDash(_cadence),
Graphics.TEXT_JUSTIFY_CENTER
);
dc.drawText(
w * 0.32,
h * 0.62,
Graphics.FONT_XTINY,
"HR",
Graphics.TEXT_JUSTIFY_CENTER
);
dc.drawText(
w * 0.68,
h * 0.62,
Graphics.FONT_XTINY,
"CAD",
Graphics.TEXT_JUSTIFY_CENTER
);
dc.drawText(
cx,
h * 0.72,
Graphics.FONT_SMALL,
_distance.format("%.1f") + " km",
Graphics.TEXT_JUSTIFY_CENTER
);
dc.drawText(
cx,
h * 0.82,
Graphics.FONT_XTINY,
formatElapsed(_elapsed),
Graphics.TEXT_JUSTIFY_CENTER
);
}
private function drawMetric(
dc,
x,
y,
label,
value,
unit
) {
dc.drawText(
x,
y,
Graphics.FONT_XTINY,
label,
Graphics.TEXT_JUSTIFY_CENTER
);
dc.drawText(
x,
y + 30,
Graphics.FONT_MEDIUM,
value,
Graphics.TEXT_JUSTIFY_CENTER
);
if (unit != "") {
dc.drawText(
x,
y + 68,
Graphics.FONT_XTINY,
unit,
Graphics.TEXT_JUSTIFY_CENTER
);
}
}
private function valueOrDash(value) {
if (value == null) {
return "--";
}
return value.format("%d");
}
private function formatElapsed(ms) {
var seconds = (ms / 1000).toNumber();
var hours = seconds / 3600;
var minutes = (seconds % 3600) / 60;
var secs = seconds % 60;
if (hours > 0) {
return hours.format("%d")
+ ":"
+ two(minutes);
}
return two(minutes)
+ ":"
+ two(secs);
}
private function two(value) {
if (value < 10) {
return "0" + value.format("%d");
}
return value.format("%d");
}
}
Where Do Garmin Speed, Heart Rate, Power and Elevation Values Come From?
Garmin automatically passes an Activity.Info object to the
compute(info) method of a Data Field.
This gives you access to many common activity metrics without creating a direct ANT+ connection yourself.
| Metric | Connect IQ Property | Native Unit |
|---|---|---|
| Current speed | currentSpeed |
m/s |
| Heart rate | currentHeartRate |
bpm |
| Cadence | currentCadence |
rpm |
| Cycling power | currentPower |
watts |
| Distance | elapsedDistance |
meters |
| Activity time | elapsedTime |
milliseconds |
| Altitude | altitude |
meters |
| Total ascent | totalAscent |
meters |
Example 1: Edge 1050 Cycling Data Field
The large 480 × 800 display on the Edge 1050 makes it possible to build a much denser cycling dashboard than on a watch.
For road cycling, gravel or indoor training, I would prioritize the metrics in roughly this order:
Speed should usually be the largest number because it needs to be readable with only a short glance. Power and cadence are useful directly below it, especially for structured training or long climbs.
Example 2: fēnix and Forerunner Running Data Field
A circular watch display requires a different design. Text near the upper-left, upper-right, lower-left and lower-right corners may be clipped by the round bezel.
Instead of filling every part of the screen, keep critical values inside the center area.
Center top: current pace
Middle left: heart rate
Middle right: running cadence
Lower center: distance
Bottom center: elapsed time
This layout works particularly well on AMOLED watches such as the Forerunner 970 and AMOLED versions of the fēnix 8 and fēnix 9.
Example 3: Hiking Data Field for fēnix or Venu X1
Hiking has very different priorities from road cycling. Instant speed is usually less important, while altitude, ascent and distance become much more useful.
ALTITUDE: 1,462 m
TOTAL ASCENT: 817 m
DISTANCE: 14.8 km
HEART RATE: 126 bpm
ELAPSED TIME: 03:42
The Venu X1 is especially interesting for this type of layout because its rectangular 448 × 486 display gives a Data Field more horizontal space than a traditional round watch.
Convert Speed into Running Pace
Garmin provides current speed in meters per second. For runners, pace is usually more useful than speed.
private function speedToPace(speedMps) {
if (speedMps == null || speedMps <= 0.01) {
return "--:--";
}
// seconds per kilometer
var paceSeconds = (1000.0 / speedMps).toNumber();
var minutes = paceSeconds / 60;
var seconds = paceSeconds % 60;
return minutes.format("%d")
+ ":"
+ two(seconds);
}
For users in the United States or other markets where pace per mile is preferred, you should respect the Garmin user's unit settings rather than forcing kilometers.
Global Garmin Apps Should Respect User Units
This is particularly important if you want downloads from the United States, United Kingdom, Europe, Australia and Asia.
A Data Field that always displays kilometers, Celsius and meters can feel unfinished to users whose Garmin settings are configured for miles, Fahrenheit or feet.
- Respect distance units.
- Respect elevation units.
- Support pace per kilometer and pace per mile.
- Avoid embedding unit text directly into graphics.
- Store UI strings in Garmin resource files.
Garmin Sensor Data: When Do You Need ANT+ Code?
You do not need to create an ANT+ connection merely to display ordinary heart rate, cadence or cycling power in a Data Field.
When those sensors are already paired with the Garmin activity profile,
values such as currentHeartRate, currentCadence
and currentPower can normally be read through Activity.Info.
Direct ANT+ access becomes useful when you need information beyond the ordinary activity value, such as detailed component information or certain sensor battery states.
Example: Reading Paired Sensor Battery Information
using Toybox.AntPlus as AntPlus;
private var _cadenceDevice = null;
private function initializeCadenceSensor() {
try {
_cadenceDevice =
new AntPlus.BikeCadence(null);
} catch (e) {
_cadenceDevice = null;
}
}
private function getCadenceBattery() {
if (_cadenceDevice == null) {
return null;
}
try {
return _cadenceDevice.getBatteryStatus(null);
} catch (e) {
return null;
}
}
If your project directly accesses ANT+ devices, remember to add the appropriate permission to the manifest.
Can a Garmin Data Field Show SRAM AXS or Electronic Shifting Information?
Connect IQ includes a shifting API that can expose information from compatible electronic shifting systems on supported Garmin devices.
A developer can inspect component identifiers and, when available, query component battery status.
using Toybox.AntPlus as AntPlus;
private var _shifting = null;
private function initializeShifting() {
try {
_shifting =
new AntPlus.Shifting(null);
} catch (e) {
_shifting = null;
}
}
private function readShiftingBatteries() {
var batteries = [];
if (_shifting == null) {
return batteries;
}
try {
var components =
_shifting.getComponentIdentifiers();
if (components == null) {
return batteries;
}
for (
var i = 0;
i < components.size();
i += 1
) {
var battery =
_shifting.getBatteryStatus(
components[i]
);
if (battery != null) {
batteries.add(battery);
}
}
} catch (e) {
}
return batteries;
}
AMOLED vs MIP: Your Garmin UI Should Not Treat Them the Same
Modern Garmin watches now span both AMOLED and Memory-In-Pixel display technologies.
For example, an AMOLED fēnix model can support a visually richer interface, while a Solar model using MIP may benefit more from high contrast, fewer colors and a simpler screen.
| Design | AMOLED | MIP |
|---|---|---|
| Colors | Rich color UI works well | Prefer simple contrast |
| Background | Black often works well | Light or dark depending on readability |
| Graphics | Gradients/icons possible | Keep graphics lightweight |
| Priority | Visual hierarchy | Outdoor readability |
Test Edge 1050, fēnix and Forerunner Layouts in the Garmin Simulator
You do not need to own every Garmin model you support. The Connect IQ Simulator can emulate different devices and screen layouts.
- Open your Monkey C project in Visual Studio Code.
- Choose Run Without Debugging.
- Select Edge 1050.
- Check the full-screen layout.
- Repeat using fēnix or Forerunner.
- Check whether content is clipped by a round screen.
- Test missing HR, cadence and power values.
I would test at least one large rectangular Edge device, one round AMOLED watch and one lower-resolution MIP watch before calling a Data Field truly multi-device compatible.
Create a Garmin Developer Key
A physical-device PRG build must be signed with a developer key. One common command-line approach is to create an RSA private key and convert it to DER format.
openssl genrsa -out developer_key.pem 4096
openssl pkcs8 -topk8 \
-inform PEM \
-outform DER \
-in developer_key.pem \
-out developer_key.der \
-nocrypt
developer_key.der file in a safe place.
Using the same key for later versions of the same project makes app maintenance easier.
Build a PRG for Garmin Edge 1050
If the SDK command-line tools are available in your PATH,
a device build can be created with monkeyc.
monkeyc \
-d edge1050 \
-f monkey.jungle \
-o UniversalGarminField.prg \
-y developer_key.der \
-r
For most beginners, however, the Visual Studio Code command Monkey C: Build for Device is easier and reduces mistakes with device IDs.
How to Sideload a Connect IQ PRG onto a Garmin Device
- Connect the Garmin device to your computer by USB.
- Build the project for that exact Garmin model.
- Locate the generated
.prgfile. - Open the Garmin storage device.
- Copy the PRG into
GARMIN/APPS. - Safely eject the Garmin device.
- Restart it if required.
- Open the activity profile and add the Connect IQ Data Field.
You only need the PRG on the Garmin itself. Development folders, source files and debug build files do not need to be copied to the device.
Garmin Official Sideloading GuideData Field Appears in Garmin but Immediately Disappears or Resets
If a custom field appears in the list but falls back to another metric, crashes or displays nothing, do not repeatedly reinstall it without checking the error log.
On supported Garmin devices, Connect IQ runtime errors can be written to:
GARMIN
└─ APPS
└─ LOGS
├─ CIQ_LOG.YAML
└─ CIQ_LOG.BAK
Check for null-value errors, unsupported APIs, drawing errors, ANT+ permissions and memory usage.
Connect IQ Debugging DocumentationCommon Garmin Connect IQ Development Mistakes
- Hard-coding Edge 1050 coordinates — the same Data Field will break on a watch or smaller field slot.
- Ignoring circular screen clipping — keep essential watch data away from corners.
- Using sensor values without null checks — heart rate, cadence and power can disappear temporarily.
- Forcing kilometers for every user — international Garmin users may use miles and feet.
- Reading sensor batteries every frame — battery information usually does not require frequent polling.
- Designing only in the simulator — always test at least one real device before publishing.
- Using too many tiny values — readability during movement is more important than maximizing data density.
Which Garmin Device Is Best for Testing a Connect IQ Data Field?
If the project is cycling-focused, I would begin with the Edge 1050. Its large display makes layout errors easy to spot and provides enough room for advanced cycling metrics.
For wearable development, the Forerunner 970 or an AMOLED fēnix 8 / fēnix 9 is a useful modern reference point because of the 454 × 454 circular screen.
I would then test a lower-resolution MIP watch if you want broader compatibility. A layout that looks excellent on a 454 × 454 AMOLED display may become cramped on a 260 × 260 or 280 × 280 watch.
Garmin Connect IQ Data Field FAQ
Can one Connect IQ Data Field support Edge 1050 and Garmin watches?
Yes. A single Connect IQ project can support multiple Garmin products. The important part is avoiding fixed screen coordinates and testing each supported layout.
Do I need a separate app for fēnix and Forerunner?
Not necessarily. If both devices support the APIs your project uses, they can usually be included as products in the same manifest.
Can I display heart rate without directly connecting to an ANT+ sensor?
Yes. In a Data Field, current heart rate can normally be obtained from
Activity.Info.currentHeartRate when Garmin has heart-rate data available.
Can Garmin Connect IQ show cycling power?
Yes. Compatible activity profiles can expose current cycling power through
Activity.Info.currentPower.
Can I build a custom running pace field?
Yes. Current speed can be converted from meters per second into minutes per kilometer or minutes per mile before being drawn on the screen.
Is Edge 1050 resolution the same as Edge 1040?
No. Edge 1050 uses a substantially higher 480 × 800 display resolution, while Edge 1040 / 1040 Solar use 282 × 470. This is another reason not to reuse fixed Edge 1040 coordinates.
Can I test Garmin apps without owning every watch?
Yes. Garmin's Connect IQ Simulator can emulate supported devices and is the normal way to check multiple screen sizes before performing final testing on physical hardware.
Can I install my own PRG without publishing it to the Connect IQ Store?
Yes. Development builds can be sideloaded onto compatible Garmin devices for testing. Publishing through the Connect IQ Store is a separate process.
Official Garmin Connect IQ Resources
- Garmin Connect IQ SDK
- Garmin Connect IQ Compatible Devices
- Garmin Edge 1050 Device Reference
- Toybox.Activity.Info API
- Garmin ANT and ANT+ Development
- Monkey C Visual Studio Code Extension
- Connect IQ Testing and Debugging
- Garmin Localization Guidelines
Final Thoughts: Build for Garmin Screen Families, Not Just One Model
The biggest improvement you can make to a Garmin Connect IQ project is to stop thinking in terms of a single product such as “an Edge 1050 Data Field” or “a fēnix Data Field.”
Instead, think in terms of screen families and activity use cases. A large rectangular Edge can display a dense cycling dashboard, a round fēnix or Forerunner needs a compact center-weighted design, and a rectangular wearable such as the Venu X1 can sit somewhere between the two.
Once the layout is based on the actual drawing context instead of fixed pixels, the same Monkey C project becomes much easier to expand to future Garmin models.
For a first project, I would start with only five or six metrics, test it on the Edge 1050 simulator and one round Garmin watch, then gradually add power, elevation, sensor battery information, electronic shifting data and localization.
댓글
댓글 쓰기