pebble/devsite/source/_guides/pebble-packages/creating-packages.md
2025-02-24 18:58:29 -08:00

7.6 KiB

title description permalink generate_toc guide_group
Creating Pebble Packages How to create Pebble Packages /guides/pebble-packages/creating-packages/ true pebble-packages

{% alert notice %} Currently package creation is only supported by the native SDK. However, you can still use packages in CloudPebble. {% endalert %}

Getting Started

To get started creating a package, run pebble new-package some-name. Make some-name something meaningful and unique; it is what you'll be publishing it under. You can check if it's taken on npm. If you'll be including a JavaScript component, you can add --javascript for a sample javascript file.

Components of a Package

C code

{% alert notice %} Tip: If you want to use an Event Service, you should use the pebble-events package to handle subscriptions from multiple packages. {% endalert %}

Packages can export C functions to their consumers, and the default package exports somelib_find_truth as an example. To export a function, it simply has to be declared in a C file in src/c/, and declared in a header file in include/. For instance:

src/c/somelib.c:

#include <pebble.h>
#include "somelib.h"

bool somelib_find_truth(void) {
    return true;
}

include/somelib.h:

#pragma once

bool somelib_find_truth(void);

Notice that include/ is already in the include path when building packages, so include files there can be included easily. By convention, packages should prefix their non-static functions with their name (in this case somelib) in order to avoid naming conflicts. If you don't want to export a function, don't include it in a file in includes/; you can instead use src/c/. You should still prefix any non-static symbols with your library name to avoid conflicts.

Once the package is imported by a consumer — either an app or package — its include files will be in a directory named for the package, and so can be included with #include <somelib/somelib.h>. There is no limit on the number or structure of files in the include directory.

JavaScript code

Packages can export JavaScript code for use in PebbleKit JS. The default JavaScript entry point for packages is always in src/js/index.js. However, files can also be required directly, according to standard node require rules. In either case they are looked up relative to their root in src/js/.

JavaScript code can export functions by attaching them to the global exports object:

src/js/index.js:

exports.addNumbers = function(a, b) {
    return a + b;
};

Because JavaScript code is scoped and namespaced already, there is no need to use any naming convention.

Resources

Packages can include resources in the same way as apps, and those resources can then be used by both the package and the app. They are included in package.json in the same manner as they are for apps. To avoid naming conflicts, packages should prefix their resource names with the package name, e.g. SOMELIB_IMAGE_LYRA.

It's best practice to define an image resource using the package name as a prefix on the resource name:

"resources": {
  "media": [
    {
      "name": "MEDIA_PACKAGE_IMAGE_01_TINY",
      "type": "bitmap",
      "file": "images/01-tiny.png"
    },
    //...
  ]
}

Create a publishedMedia entry if you want to make the images available for {% guide_link user-interfaces/appglance-c "AppGlance slices" %} or {% guide_link pebble-timeline/pin-structure "Timeline pins" %}.

"resources": {
  //...
  "publishedMedia": [
    {
      "name": "MEDIA_PACKAGE_IMAGE_01",
      "glance": "MEDIA_PACKAGE_IMAGE_01_TINY",
      "timeline": {
        "tiny": "MEDIA_PACKAGE_IMAGE_01_TINY",
        "small": "MEDIA_PACKAGE_IMAGE_01_SMALL",
        "large": "MEDIA_PACKAGE_IMAGE_01_LARGE"
      }
    }
  ]
}

Note: Do NOT assign an id when defining publishedMedia within packages, see {% guide_link pebble-packages/using-packages "Using Packages" %}.

Resource IDs are not assigned until the package has been linked with an app and compiled, so RESOURCE_ID_* constants cannot be used as constant initializers in packages. To work around this, either assign them at runtime or reference them directly. It is also no longer valid to try iterating over the resource id numbers directly; you must use the name defined for you by the SDK.

AppMessage Keys

Libraries can use AppMessage keys to reduce friction when creating a package that needs to communicate with the phone or internet, such as a weather package. A list of key names can be included in package.json, under pebble.messageKeys. These keys will be allocated numbers at app build time. We will inject them into your C code with the prefix MESSAGE_KEY_, e.g. MESSAGE_KEY_CURRENT_TEMP.

If you want to use multiple keys as an 'array', you can specify a name like ELEMENTS[6]. This will create a single key, ELEMENTS, but leave five empty spaces after it, for a total of six available keys. You can then use arithmetic to access the additional keys, such as MESSAGE_KEY_ELEMENTS + 5.

To use arrays in JavaScript you will need to know the actual numeric values of your keys. They will exist as keys on an object you can access via require('message_keys'). For instance:

var keys = require('message_keys');
var elements = ['honesty', 'generosity', 'loyalty', 'kindness', 'laughter', 'magic'];
var dict = {}
for (var i = 0; i < 6; ++i) {
	dict[keys.ELEMENTS + i] = elements[i];
}
Pebble.sendAppMessage(dict, successCallback, failureCallback);

Building and testing

Run pebble build to build your package. You can install it in a test project using pebble package install ../path/to/package. Note that you will have to repeat both steps when you change the package. If you try symlinking the package, you are likely to run into problems building your app.

Publishing

Publishing a Pebble Package requires you to have an npm account. For your convenience, you can create or log in to one using pebble package login (as distinct from pebble login). Having done this once, you can use pebble package publish to publish a package.

Remember to document your package! It isn't any use to anyone if they can't figure out how to use it. README.md is a good place to include some documentation.

Adding extra metadata to package.json is also worthwhile. In particular, it is worth specifying:

  • repository: if your package is open source, the repo you can find it in. If it's hosted on github, "username/repo-name" works; otherwise a git URL.
  • license: the license the package is licensed under. If you're not sure, try choosealicense.com. You will also want to include a copy of the full license text in a file called LICENSE.
  • description: a one-sentence description of the package.

For more details on package.json, check out npm's package.json documentation.