# Package com.codename1.surfaces

package com.codename1.surfaces

External surfaces: home-screen widgets and live activities from one declarative API.

Both features answer the same developer question -- how do I keep a live source of information outside my app? -- so Codename One models them as one concept. A widget is persistent, user-placed and content-driven (weather, next meeting, delivery status on the home screen). A live activity is transient, app-started and progress-driven (the delivery that is out RIGHT NOW, a running timer, a live score on the iOS lock screen / Dynamic Island, an ongoing Android notification, a floating desktop pill). They share the layout model, the serialization, the state mechanism and the action model.

##### The dead-process rule

Surfaces render while your app process may not be running. Everything you hand this API is therefore turned into plain data at publish time: layouts serialize to a compact JSON descriptor, images are encoded to named PNG blobs, and "callbacks" are string action ids that open the app and are delivered to your `SurfaceActionHandler` on the EDT (queued across a cold start). Layout text embeds `${key}` placeholders resolved from a per-entry state map, so content changes are cheap re-publishes of data, not layouts.

##### The layout model

A small sealed catalog of nodes every platform can render natively -- `SurfaceColumn`, `SurfaceRow`, `SurfaceBox`, `SurfaceText`, `SurfaceDynamicText`, `SurfaceImage`, `SurfaceProgress`, `SurfaceVector`, `SurfaceSpacer` -- with shared styling (padding, background, corner radius, alignment, weight, size, action). `SurfaceDynamicText` is the headline feature: countdowns and elapsed-time text the OS animates on its own clock, so a delivery ETA ticks every second with zero app wakeups. `SurfaceVector` covers the widgets the template catalog cannot express -- clocks, gauges, dials -- with a retained list of vector drawing ops (fills, strokes, arcs, text, rotation groups) replayed natively by every renderer.

##### The lowest common denominator contract

Android app widgets (`RemoteViews`) are the constrained platform; the catalog is designed to its floor and degrades as follows:

Node | iOS (SwiftUI) | Android (RemoteViews) | Caveat
--- | --- | --- | ---
Column/Row | VStack/HStack | LinearLayout | weight maps to layout_weight
Box | ZStack | FrameLayout | child alignment via 9-way enum
Text | Text | TextView | Android renders light/regular/medium as regular, semibold/bold as bold
DynamicText timer | Text(date, style:) | Chronometer | native on both
DynamicText time | Text(date, style: .time) | TextClock | native on both
DynamicText date/relative | native | static text | Android refreshes only on next update
Image | Image | ImageView | named PNG blobs, content-hash dedup
Progress linear | ProgressView | ProgressBar | value 0..1 or state key
Progress circular | Gauge | falls back to linear | Android widgets lack determinate circular
Progress date interval | native animation | frozen at refresh | iOS-only nicety
Vector | SwiftUI Canvas | bitmap rendered in-process | desktop: CN1 Graphics; Android renders vec nodes as raster, so very large vec nodes cost bitmap budget
Spacer | Spacer | weighted View |
corner radius | clipShape | background drawable | may render square below Android 12
node action | Link / widgetURL | setOnClickPendingIntent | small iOS widgets honor only the root action

Descriptors are limited to 8 nesting levels; keep payloads (JSON + images) comfortably under 200kb -- the iOS widget extension runs in about 30mb of memory and Android parcels rendered widgets over a 1mb binder transaction.

##### Example: an analog clock widget

A `SurfaceVector` face plus per-minute timeline entries driving the hand angles. Angles use the clock convention (degrees, 0 = 12 o'clock, clockwise positive); the OS flips the entries on schedule, so the clock stays correct for an hour with zero app wakeups:

    SurfaceVector face = new SurfaceVector(200, 200)
            .fillEllipse(100, 100, 96, 96, SurfaceColor.BACKGROUND)
            .beginRotation("hourAngle", 100, 100)
                .line(100, 100, 100, 52, 8, SurfaceColor.LABEL).endRotation()
            .beginRotation("minuteAngle", 100, 100)
                .line(100, 100, 100, 24, 5, SurfaceColor.ACCENT).endRotation();
    WidgetTimeline t = new WidgetTimeline().setContent(face);
    for (int m = 0; m < 60; m++) {
        int totalMinutes = hourOfDay * 60 + minute + m;
        Map<String, Object> state = new HashMap<String, Object>();
        state.put("minuteAngle", totalMinutes % 60 * 6f);
        state.put("hourAngle", totalMinutes % 720 * 0.5f);
        t.addEntry(new Date(minuteStart + m * 60000L), state);
    }
    Surfaces.publish("analog_clock", t);

##### Build-time manifest: `surfaces.json`

Platform widget galleries are compiled into the native app, so widget kinds must be known at build time. Keep a `surfaces.json` in your project resources (next to your icons) mirroring your runtime `WidgetKind` registrations:

    {
      "liveActivities": true,
      "kinds": [
        { "id": "delivery_status", "name": "Delivery", "description": "Track your order",
          "iosFamilies": ["systemSmall", "systemMedium"] }
      ]
    }

##### Refresh and updates

This version updates surfaces from the running app: publish a `WidgetTimeline` of dated entries (the OS flips entries on schedule without waking you), implement `com.codename1.background.BackgroundFetch` to re-publish periodically, and push live activity state with `LiveActivity.update(...)`. Push-driven updates (server-sent widget content and ActivityKit push tokens) are planned; the wire format already accommodates them.

##### Zero cost when unused

Referencing this package makes the build inject the native plumbing (WidgetKit extension and app group on iOS, widget receivers on Android). Apps that never touch it get none of it. On unsupported ports every entry point is an inert no-op.

- Related Packages
  Package
  Description
  com.codename1.surfaces.spi
  The platform seam of the external surfaces framework.
- Class
  Description
  LiveActivity
  A running live activity: an ongoing-state surface (delivery, timer, ride, score) presented on the iOS lock screen and Dynamic Island, as an ongoing Android notification, or as a floating pill window on desktop.
  LiveActivityDescriptor
  Describes a live activity: an ongoing-state surface (delivery, timer, ride, score) that stays visible outside the app while it is in progress.
  SurfaceActionEvent
  A user interaction with an external surface: the user tapped a node that carries an action id.
  SurfaceActionHandler
  Receives surface action events.
  SurfaceAlignment
  Nine-way alignment of a node within its parent.
  SurfaceBox
  A container that stacks its children on top of each other.
  SurfaceColor
  A color used on an external surface.
  SurfaceColumn
  A container that stacks its children vertically.
  SurfaceContainer
  The base class of surface nodes that hold children: `SurfaceColumn`, `SurfaceRow` and `SurfaceBox`.
  SurfaceDynamicText
  A date-driven text node the operating system animates natively -- the headline feature for timers, delivery ETAs and elapsed-time displays: a countdown keeps ticking every second on the widget or Dynamic Island even though the app process is not running.
  SurfaceFontWeight
  Font weight of a surface text node.
  SurfaceImage
  An image node.
  SurfaceNode
  The base class of all surface layout nodes.
  SurfaceProgress
  A progress indicator node.
  SurfaceRasterizer
  A shared software renderer for desktop ports (the JavaSE simulator, the native Windows and Linux ports): draws a parsed surface descriptor node into a mutable Codename One `Image` using only `Graphics` primitives -- no `Container`/`Label` components and no theme dependence, so the output looks the same on every desktop surface.
  SurfaceRasterizer.ActionRect
  The absolute bounds of a node that carries a tap action, in pixels of the rasterized image.
  SurfaceRasterizer.Result
  The output of a rasterization pass: pixels, action hit rectangles and the next re-render deadline.
  SurfaceRow
  A container that lays its children out horizontally.
  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.
  SurfaceSerializer
  Serializes surface descriptors to the canonical wire format shared by every port: a compact JSON document plus PNG blobs named by content hash.
  SurfaceSpacer
  A flexible spacer that absorbs the leftover space of its parent row or column, pushing its siblings apart.
  SurfaceText
  A static text node.
  SurfaceVector
  A retained vector drawing node: a small catalog of fill/stroke/text operations recorded in paint order and replayed natively by every platform renderer (SwiftUI `Canvas` on iOS, an in-process bitmap on Android, Codename One `Graphics` on desktop).
  WidgetKind
  Declares one kind of home-screen widget the app offers (an app may offer several).
  WidgetSize
  The size families a widget kind supports.
  WidgetTimeline
  The content of a widget kind: a layout descriptor plus a timeline of dated state snapshots.
  WidgetTimeline.Entry
  One dated state snapshot within a timeline.