github rive-app/rive-android 11.16.0

3 hours ago

Features

GPU-loss reporting and recovery

Apps can now observe RiveWorker.renderContextStatus, a StateFlow<RenderContextStatus> that changes from Ready to Lost when Rive detects a lost GPU device or rendering context. This gives apps a way to respond to OpenGL or Vulkan driver failures instead of leaving the affected content frozen indefinitely. (Change)

After a loss, the Rive composable and RiveCanvasSession stop their frame loops, and drawToBuffer throws RiveDrawToBufferException. Recovery is application-controlled: release the affected worker and its resources, create a new worker, and reload the content. A lost worker does not return to Ready. Detection occurs during rendering, and the status is delivered through worker polling. Not every driver failure can be detected.

The sample app includes Compose and Canvas examples that replace the worker and reload its resources after a loss. (Change)

Nested data converters

Data bindings on a converter's own properties can now use converters themselves. This supports combinations such as converting an enum to a number before using it in a formula, or applying a converter to a string-template argument or scripted converter input. Nested interpolators also continue advancing until they settle. These combinations are configured in the Rive Editor and play back on Android. (Change)

Animated font selection

Font selection can now be keyframed in the Rive Editor and played back on Android. A text style switches to the font selected by each keyframe, and exported files include the fonts those keyframes reference. (Change)

Capture-phase pointer listeners

Pointer listeners configured with the capture phase in the Rive Editor can handle a press before listeners deeper in the component tree. This lets a containing artboard intercept interactions with a nested component without editing that component. A capture listener that claims a press keeps control of that pointer's gesture until release. (Change)

Images as pointer targets

Pointer listeners can now target images, including their visible mesh or N-slice geometry. Images inside a targeted group also contribute to its hit area. This behavior requires a file exported with the new .riv 7.5 format, so re-export existing content to enable it. Older files retain their previous hit-testing behavior. (Change)

Fixes

  • FCNT driver crashes: Specific FCNT firmware could crash inside IMGeglMakeCurrent. On A402FC/V54RS51B, FCG02/V54RK51B, F-52E/V54RD51B, and M07/V54RM51B, Rive now requires Vulkan even when OpenGL was requested. If Vulkan initialization fails, initialization fails without retrying the affected OpenGL driver. Legacy uses its existing Android Canvas fallback, whose rendering and feature support can differ. Other devices keep their existing backend selection. (Fix)
  • Compose surface creation and cleanup: Android could report zero or negative initial surface dimensions, causing a crash. Surface creation now waits for valid dimensions. A surface created and destroyed before recomposition could also escape cleanup. Disposal now follows the texture destruction callback. (Fix)
  • Nested state machine events: A deleted state machine could remain registered for events from nested artboards, leaving a later event to call freed memory. Listener links are now removed when either side is destroyed, including when virtualized list rows are recycled. (Fix)
  • Converter lifetimes: Rebinding or destroying formula and operation converters could leave stale subscriptions on view model values, causing crashes on a later value change. Converters now detach from their previous sources and release their subscriptions safely. (Fix)
  • Listener view model assignments: A listener action assigning a view model from another property could accidentally assign the enclosing instance instead, causing recursive updates and a stack overflow. It now assigns the selected property value. (Fix)
  • Trigger comparisons: Comparing triggers could let one fire advance a state machine layer more than once. Comparisons now respect whether that layer has already used the fire, including when the trigger is on the right side of the comparison. (Fix)
  • Deformed artboard input: Pointer hits on a nested artboard drawn through a mesh or N-slice could land at its undeformed position. Input now follows the drawn geometry. Focus rings and semantics bounds still use the undeformed transform. (Fix)
  • Right-to-left list rows: Rows added after the first frame could keep left-to-right layout under a right-to-left parent, putting spacing and corners on the wrong side. New rows now inherit their parent's direction before layout. This also avoids extra layout passes. (Fix)
  • Text ellipsis: Right-to-left text could put its ellipsis at the wrong end, and shortened right- or center-aligned lines could extend outside their box. Ellipsis placement and alignment now follow the paragraph. An ellipsis also adopts the correct font and size when only one of those changes between runs. (Fix, Fix)
  • Animated text memory: Animating text modifiers could continually append duplicate line records. Those records are now cleared when render styles rebuild, preventing unbounded memory growth. (Fix)
  • Text path effects: Trim and dash effects could be drawn repeatedly when text modifiers produced different glyph opacities, making the result too opaque. The effect now draws once at the highest glyph opacity. Per-glyph opacity is still not preserved through these effects. (Fix)
  • Korean line wrapping: Korean text could wrap between Hangul syllables after the Unicode line-breaker change. It now keeps Korean words together at spaces again. (Fix)
  • Path hangs and crashes: Path lookups at 100% could return an unset position, and long sequential trims could spend excessive time walking loops. End positions and long trims now resolve correctly. Strokes without paint and path effects waiting for an unavailable path also no longer crash. (Fix)
  • Outside stroke seams: A thin antialiasing gap could appear between a fill and its outside stroke. The stroke's inner edge now covers that gap. (Fix)
  • Nested opacity: A parent opacity change could reach a nested artboard one advance late, producing a blank frame when scripts switched between artboards. Nested paints now update in the same advance. (Fix)
  • Luau gradients and vectors: Gradient construction and numeric vector indexing could access stale stack memory after an allocation. Arguments are now copied or read in a safe order. Gradient stops also no longer accumulate stack entries that could cause a stack overflow. (Fix)
  • Luau module initialization: Non-terminating module initialization could hang the runtime before normal script callbacks began. Module execution now arms timeout checks, although some blocking script patterns can still evade interruption. (Fix)
  • GPU Canvas resource bindings: Reusing a resource layout across shaders could bind textures to the wrong slots on OpenGL, producing missing or incorrect output. Bindings now use the active pipeline's slots. (Fix)
  • MP3 playback: MP3 playback now accounts for encoder padding for gapless playback, and reported durations match decoded audio more accurately, including files with an extra frame counted in their header. Some MP3 durations therefore become slightly shorter. (Fix, Fix)

Performance

Responsive Canvas startup and resizing

RiveCanvasSession no longer blocks the main thread while waiting for its first rendered frame, either at startup or after a resize. In a release-build Vulkan cold-start measurement on a Galaxy S23, time spent on the main thread in the first render() call fell from 143 ms on average to at most 0.1 ms. The first frame still takes time to render, but the UI thread can continue working while it waits. The public HardwareRenderBuffer constructor retains its existing first-frame wait behavior. (Change)

Faster list updates and hug layouts

Adding and removing data-bound list rows now avoids repeated layout passes and list scans. Text also reuses cached glyph outlines without copying each outline for every path. In an M2 Max production-build benchmark, adding 100 rows to a UI list fell from 6.80 ms to 4.39 ms after the initial-layout change. Gains depend on the content. (Change)

Hug containers can also reuse a previous measurement when new size limits still allow the same content size, avoiding repeated measurement of the entire subtree. Switching a Solo with no layout content no longer rebuilds the artboard's layout-child collection. (Change, Change)

Less converter update work

Converters now cache whether their nested bindings need to advance. Formula-heavy scenes skip repeated walks through tokens and bindings that cannot change with time, while nested interpolators continue updating. (Change)

Leaner rendering batches and shader data

The renderer combines compatible drawing ranges into shared batches, reducing CPU bookkeeping. Path and paint data also share a more compact buffer, reducing uploads and buffer reads in common drawing paths. (Change, Change)


Full comparison

Don't miss a new rive-android release

NewReleases is sending notifications on new releases.