--- # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. title: SDK 3.x Migration Guide description: Migrating Pebble apps from SDK 2.x to SDK 3.x. permalink: /guides/migration/migration-guide-3/ generate_toc: true guide_group: migration order: 2 --- This guide provides a detailed list of the changes to existing APIs in Pebble SDK 3.x. To migrate an older app's code successfully from Pebble SDK 2.x to Pebble SDK 3.x, consider the information outlined here and make the necessary changes if the app uses a changed API. The number of breaking changes in SDK 3.x for existing apps has been minimized as much as possible. This means that: * Apps built with SDK 2.x **will continue to run on firmware 3.x without any recompilation needed**. * Apps built with SDK 3.x will generate a `.pbw` file that will run on firmware 3.x. ## Backwards Compatibility Developers can easily modify an existing app (or create a new one) to be compilable for both Pebble/Pebble Steel as well as Pebble Time, Pebble Time Steel, and Pebble Time Round by using `#ifdef` and various defines that are made available by the SDK at build time. For example, to check that the app will run on hardware supporting color: ```c #ifdef PBL_COLOR window_set_background_color(s_main_window, GColorDukeBlue); #else window_set_background_color(s_main_window, GColorBlack); #endif ``` When the app is compiled, it will be built once for each platform with `PBL_COLOR` defined as is appropriate. By catering for all cases, apps will run and look good on both platforms with minimal effort. This avoids the need to maintain two Pebble projects for one app. In addition, as of Pebble SDK 3.6 there are macros that can be used to selectively include code in single statements. This is an alternative to the approach shown above using `#ifdef`: ```c window_set_background_color(s_main_window, PBL_IF_COLOR_ELSE(GColorDukeBlue, GColorBlack)); ``` See {% guide_link best-practices/building-for-every-pebble %} to learn more about these macros, as well as see a complete list. ## PebbleKit Considerations Apps that use PebbleKit Android will need to be re-compiled in Android Studio (or similar) with the PebbleKit Android **3.x** (see {% guide_link communication/using-pebblekit-android %}) library in order to be compatible with the Pebble Time mobile application. No code changes are required, however. PebbleKit iOS developers remain unaffected and their apps will continue to run with the new Pebble mobile application. However, iOS companion apps will need to be recompiled with PebbleKit iOS **3.x** (see {% guide_link migration/pebblekit-ios-3 "PebbleKit iOS 3.0 Migration Guide" %}) to work with Pebble Time Round. ## Changes to appinfo.json There is a new field for tracking which version of the SDK the app is built for. For example, when using 3.x SDK add this line to the project's `appinfo.json`. ``` "sdkVersion": "3" ``` Apps will specify which hardware platforms they support (and wish to be built for) by declaring them in the `targetPlatforms` field of the project's `appinfo.json` file. ``` "targetPlatforms": [ "aplite", "basalt", "chalk" ] ``` For each platform listed here, the SDK will generate an appropriate binary and resource pack that will be included in the `.pbw` file. This means that the app is actually compiled and resources are optimized once for each platform. The image below summarizes this build process:  > Note: If `targetPlatforms` is not specified in `appinfo.json` the app will be > compiled for all platforms. Apps can also elect to not appear in the app menu on the watch (if is is only pushing timeline pins, for example) by setting `hiddenApp`: ``` "watchapp": { "watchface": false, "hiddenApp": true }, ``` ## Project Resource Processing SDK 3.x enhances the options for adding image resources to a Pebble project, including performing some pre-processing of images into compatible formats prior to bundling. For more details on the available resource types, check out the {% guide_link app-resources %} section of the guides. ## Platform-specific Resources **Different Resources per Platform** It is possible to include different versions of resources on only one of the platforms with a specific type of display. Do this by appending `~bw` or `~color` to the name of the resource file and the SDK will prefer that file over another with the same name, but lacking the suffix. This means is it possible to can include a smaller black and white version of an image by naming it `example-image~bw.png`, which will be included in the appropriate build over another file named `example-image.png`. In a similar manner, specify a resource for a color platform by appending `~color` to the file name. An example file structure is shown below. ```text my-project/ resources/ images/ example-image~bw.png example-image~color.png src/ main.c appinfo.json wscript ``` This resource will appear in `appinfo.json` as shown below. ``` "resources": { "media": [ { "type": "bitmap", "name": "EXAMPLE_IMAGE", "file": "images/example-image.png" } ] } ``` Read {% guide_link app-resources/platform-specific %} for more information about specifying resources per-platform. **Single-platform Resources** To only include a resource on a **specific** platform, add a `targetPlatforms` field to the resource's entry in the `media` array in `appinfo.json`. For example, the resource shown below will only be included for the Basalt build. ``` "resources": { "media": [ { "type": "bitmap", "name": "BACKGROUND_IMAGE", "file": "images/background.png", "targetPlatforms": [ "basalt" ] } ] } ``` ## Changes to wscript To support compilation for multiple hardware platforms and capabilities, the default `wscript` file included in every Pebble project has been updated. If a project uses a customized `wscript` file and `pebble convert-project` is run (which will fully replace the file with a new compatible version), the `wscript` will be copied to `wscript.backup`. View [this GitHub gist](https://gist.github.com/pebble-gists/72a1a7c85980816e7f9b) to see a sample of what the new format looks like, and re-add any customizations afterwards. ## Changes to Timezones With SDK 2.x, all time-related SDK functions returned values in local time, with no concept of timezones. With SDK 3.x, the watch is aware of the user's timezone (specified in Settings), and will return values adjusted for this value. ## API Changes Quick Reference ### Compatibility Macros Since SDK 3.0-dp2, `pebble.h` includes compatibility macros enabling developers to use the new APIs to access fields of opaque structures and still be compatible with both platforms. An example is shown below: ```c static GBitmap *s_bitmap; ``` ```c // SDK 2.9 GRect bounds = s_bitmap->bounds; // SDK 3.x GRect bounds = gbitmap_get_bounds(s_bitmap); ``` ### Comparing Colors Instead of comparing two GColor values directly, use the new ``gcolor_equal`` function to check for identical colors. ```c GColor a, b; // SDK 2.x, bad if (a == b) { } // SDK 3.x, good if (gcolor_equal(a, b)) { } ``` > Note: Two colors with an alpha transparency(`.a`) component equal to `0` > (completely transparent) are considered as equal. ### Assigning Colors From Integers Specify a color previously stored as an `int` and convert it to a `GColor`: ```c GColor a; // SDK 2.x a = (GColor)persist_read_int(key); // SDK 3.x a.argb = persist_read_int(key); /* OR */ a = (GColor){.argb = persist_read_int(key)}; ``` ### Specifying Black and White The internal representation of SDK 2.x colors such as ``GColorBlack`` and ``GColorWhite`` have changed, but they can still be used with the same name. ### PebbleKit JS Account Token In SDK 3.0 the behavior of `Pebble.getAccountToken()` changes slightly. In previous versions, the token returned on Android could differ from that returned on iOS by dropping some zero characters. The table below shows the different tokens received for a single user across platforms and versions: | Platform | Token | |:---------|-------| | iOS 2.6.5 | 29f00dd7872ada4bd14b90e5d49568a8 | | iOS 3.x | 29f00dd7872ada4bd14b90e5d49568a8 | | Android 2.3 | 29f0dd7872ada4bd14b90e5d49568a8 | | Android 3.x | 29f00dd7872ada4bd14b90e5d49568a8 | > Note: This process should **only** be applied to new tokens obtained from > Android platforms, to compare to tokens from older app versions. To account for this difference, developers should adapt the new account token as shown below. **JavaScript** ```js function newToOld(token) { return token.split('').map(function (x, i) { return (x !== '0' || i % 2 == 1) ? x : ''; }).join(''); } ``` **Python** ```python def new_to_old(token): return ''.join(x for i, x in enumerate(token) if x != '0' or i % 2 == 1) ``` **Ruby** ```ruby def new_to_old(token) token.split('').select.with_index { |c, i| (c != '0' or i % 2 == 1) }.join('') end ``` **PHP**