public final class Surfaces

  1. Object
  2. Surfaces

The static entry point for external surfaces: home-screen widgets and live activities – the two faces of one concept, a live source of information that resides outside your app. Declare your widget kinds and register an action handler in init(), then publish content whenever your data changes:

Surfaces.registerWidgetKind(new WidgetKind("delivery_status")
        .setDisplayName("Delivery").setDescription("Track your order"));
Surfaces.setActionHandler(evt -> showOrder(evt.getParams()));
...
Surfaces.publish("delivery_status", new WidgetTimeline()
        .setContent(layout).addEntry(new Date(), state));

How surfaces render

Surfaces render while your app process may be dead: the published timeline is serialized (a JSON descriptor plus PNG blobs) and persisted where the platform renderer can reach it – the iOS widget extension, the Android widget provider or a desktop surface window. Layouts embed ${key} placeholders resolved from each timeline entry’s state map, and SurfaceDynamicText countdowns tick natively on the OS clock with no app wakeups. To refresh content periodically implement com.codename1.background.BackgroundFetch and re-publish there.

Widget kinds must also be declared at build time in the project’s surfaces.json resource – the platform widget galleries are compiled into the native app. See the package documentation.

Zero cost when unused

Merely referencing this package makes the build inject the native plumbing (the WidgetKit extension and app group on iOS, the widget receivers on Android). Apps that never touch com.codename1.surfaces get none of it. On the simulator the Widgets preview window renders published surfaces; on unsupported ports the API is an inert no-op.

Methods

public static boolean areWidgetsSupported()Returns true when this platform can render home-screen (or desktop) widgets.
public static void registerWidgetKind(WidgetKind kind)Declares a widget kind at runtime.
public static List<WidgetKind> getRegisteredKinds()Returns the widget kinds registered so far.
public static void setDiagnosticsEnabled(Boolean enabled)Overrides whether the simulator-only surface diagnostics run.
public static boolean isDiagnosticsEnabled()Returns true when the simulator-only surface diagnostics are currently active.
public static void publish(String kindId, WidgetTimeline timeline)Publishes a widget kind’s content, atomically replacing any previously published timeline and asking the platform to re-render the kind’s widget instances.
public static void publishRemote(String kindId, String timelineJson)Push-framework entry point for a server-rendered timeline descriptor.
public static void publishRemote(String kindId, String timelineJson, Map<String, byte[]> images)As publishRemote(String,String), with the imagery the descriptor references.
public static void reloadWidgets(String kindId)Asks the platform to re-render widgets from their already-published timelines.
public static int getInstalledWidgetCount(String kindId)Returns the number of widget instances of a kind the user placed on the platform surface, or 0 when none exist or the platform cannot tell.
public static void setActionHandler(SurfaceActionHandler handler)Registers the single handler receiving surface action events on the EDT.
public static void dispatchAction(String source, String actionId, Map<String, Object> params)Framework/port entry point: delivers a surface action to the app.
public static void setBridge(SurfaceBridge b)Framework/port/test entry point: overrides the bridge resolved from the platform port.

Inherited methods

Method details

areWidgetsSupported

public static boolean areWidgetsSupported()
Returns true when this platform can render home-screen (or desktop) widgets.

Returns

true when widgets are supported

registerWidgetKind

public static void registerWidgetKind(WidgetKind kind)
Declares a widget kind at runtime. Call once per kind, typically from init(). The id must match a kind declared in the project’s surfaces.json build-time manifest; a mismatch logs a prominent warning on supporting platforms.

Parameters

kind WidgetKind
the kind declaration

getRegisteredKinds

public static List<WidgetKind> getRegisteredKinds()
Returns the widget kinds registered so far.

setDiagnosticsEnabled

public static void setDiagnosticsEnabled(Boolean enabled)

Overrides whether the simulator-only surface diagnostics run. They are on in the simulator and off everywhere else, which is almost always what you want: they catch usage that works in the simulator but stalls or silently does nothing on a device (rasterizing a surface image on the EDT, publishing to a kind that was never registered, republishing far past the platform’s reload budget), and they cost nothing in a shipped build because they never run there. Diagnostics that are certain to misbehave on a device throw IllegalStateException; the rest log a one-time warning.

Pass null to restore the default behaviour. Turning them off is a last resort for a case a check gets wrong – please report it if you hit one.

Parameters

enabled Boolean
true to force diagnostics on, false to force them off, null for the default

isDiagnosticsEnabled

public static boolean isDiagnosticsEnabled()
Returns true when the simulator-only surface diagnostics are currently active.

Returns

true when diagnostics run for this process

publish

public static void publish(String kindId, WidgetTimeline timeline)

Publishes a widget kind’s content, atomically replacing any previously published timeline and asking the platform to re-render the kind’s widget instances. A no-op on platforms without widget support.

Threading

Callable from any thread – including com.codename1.background.BackgroundFetch#performBackgroundFetch(long, com.codename1.util.Callback) callbacks while the app UI is not running (on Android the fetch runs in a background service with no Activity at all). Publishing is data-only: the timeline is serialized, persisted where the platform renderer can reach it and the renderer is poked asynchronously. Implementing background fetch and re-publishing there is the intended way to keep widgets fresh; see the com.codename1.surfaces.spi package documentation for the per-platform background update story.

A background thread is the RIGHT thread, not merely a permitted one. On a device this writes the payload into the shared container and makes a synchronous native call, and any SurfaceImage holding an Image that is not an EncodedImage is rasterized here – on iOS that encode blocks the caller on the platform UI thread while the pixels are read back off the GPU. Publishing on the EDT therefore stalls the UI on hardware while looking instantaneous in the simulator. Pass EncodedImages and publish off the EDT; the simulator diagnostics flag both mistakes (see setDiagnosticsEnabled(Boolean)).

Parameters

kindId String
the widget kind id
timeline WidgetTimeline
the content to publish

publishRemote

public static void publishRemote(String kindId, String timelineJson)

Push-framework entry point for a server-rendered timeline descriptor. The descriptor uses the same wire format as publish(). The descriptor is persisted directly once the Codename One runtime receives it. A platform that doesn’t run application code for a background push applies it when the application next starts or resumes.

Equivalent to publishRemote(String,String,Map) with no imagery. A descriptor that references an image by name renders a gap where it should be, so prefer the overload whenever the artwork travelled with the descriptor.

publishRemote

public static void publishRemote(String kindId, String timelineJson, Map<String, byte[]> images)

As publishRemote(String,String), with the imagery the descriptor references.

A timeline’s node tree names its images rather than embedding them – SurfaceSerializer hashes the bytes and puts the hash on the wire – so a descriptor that arrived from somewhere else is only complete if its side-map arrived too. Without this overload publishRemote discarded the imagery unconditionally and every referenced image rendered as a gap.

The two callers are a server push and the phone-to-watch mirror, which forwards a phone-side publish() of a watch-bearing kind to the watch. Both are the same operation: a descriptor produced elsewhere, applied here.

Parameters

kindId String
the widget kind id
timelineJson String
the serialized timeline, in the same wire format publish() produces
images Map<String, byte[]>
the referenced images by name, or an empty map when the descriptor names none

reloadWidgets

public static void reloadWidgets(String kindId)
Asks the platform to re-render widgets from their already-published timelines.

Parameters

kindId String
the kind to reload, or null for all kinds

getInstalledWidgetCount

public static int getInstalledWidgetCount(String kindId)
Returns the number of widget instances of a kind the user placed on the platform surface, or 0 when none exist or the platform cannot tell. Useful to skip publishing work when no widget is installed.

Parameters

kindId String
the widget kind id

Returns

the installed instance count, or 0

setActionHandler

public static void setActionHandler(SurfaceActionHandler handler)
Registers the single handler receiving surface action events on the EDT. Registration flushes any actions queued before it (e.g. the tap that cold-started the app), in arrival order, with their cold-start flag set.

Parameters

handler SurfaceActionHandler
the handler, or null to clear

dispatchAction

public static void dispatchAction(String source, String actionId, Map<String, Object> params)
Framework/port entry point: delivers a surface action to the app. Ports call this after decoding their platform payload (deep link, intent extras, window click). Handles EDT marshaling; when no handler is registered yet the event is queued and flagged cold start.

Parameters

source String
the widget kind id or live activity type
actionId String
the action id of the tapped node
params Map<String, Object>
the action parameters, may be null

setBridge

public static void setBridge(SurfaceBridge b)
Framework/port/test entry point: overrides the bridge resolved from the platform port. Passing null restores platform resolution.

Parameters

b SurfaceBridge
the bridge, or null to resolve from the platform again