Navigation Bubble

Navigation Bubble presents lightweight navigation information — speed above all — on the DuoDash interface. This page covers how a third-party tweak feeds it data from an application it supports.

The Developer API is not published yet. Every symbol on this page is an illustrative placeholder, not the final DuoDash SDK. The architecture and the rules are what to design against; the names are not. Developer guide overview

Purpose

Navigation Bubble is a DuoDash Core Tweak that presents lightweight navigation-related information on the DuoDash interface. One of its primary uses is displaying speed information.

A third-party tweak obtains speed or other supported navigation information from an application and provides it to Navigation Bubble. Navigation Bubble is responsible for presenting the information; your tweak is responsible for obtaining and interpreting the original data.

Do not attempt to manipulate Navigation Bubble UI elements directly. Provide normalized data to DuoDash and let it render.

Data flow

A typical integration works as follows.

Target Navigation App
        │
        │ 1. Third-party tweak observes app
        ▼
Application-Specific Tweak
        │
        │ 2. Extract speed/navigation data
        │ 3. Normalize data
        ▼
DuoDash Navigation Bubble API
        │
        │ 4. Validate/update
        ▼
Navigation Bubble
        │
        │ 5. Render
        ▼
CarPlay / DuoDash UI

Example: a speed provider

Suppose you are writing a tweak for a navigation application that internally exposes the current vehicle speed. The tweak would:

  1. Observe the relevant application object or data source.
  2. Extract the current speed.
  3. Determine the unit used by the source application.
  4. Convert or normalize the value if required.
  5. Send the value to Navigation Bubble.
  6. Continue providing updates while the source remains valid.

Conceptually:

// Illustrative example only.
// Replace with the official DuoDash API when available.

DDNavigationBubbleData *data = [DDNavigationBubbleData new];

data.speed            = currentSpeed;
data.speedUnit        = DDSpeedUnitKPH;
data.sourceIdentifier = @"com.example.navigation";

[[DDNavigationBubble sharedInstance] updateData:data];

The classes and methods above are illustrative placeholders. They do not represent the final DuoDash SDK or API.

Recommended data model

The final DuoDash API may expose some or all of the following fields:

speed
speedUnit
speedLimit
speedLimitUnit
sourceIdentifier
timestamp
accuracy
valid

Possible future navigation fields may include:

distanceToNextTurn
nextTurnType
nextStreetName
remainingDistance
estimatedArrivalTime
routeState

Only provide fields for which you have reliable data. Do not fabricate missing values.

Source identification

Every third-party provider should have a unique source identifier. The recommended format is:

<developer>.<application>.<provider>

For example:

com.example.googlemaps.speedprovider

or, if bundle identifiers are used:

com.google.Maps

The final identifier format will follow the DuoDash SDK specification. Source identifiers are what allow DuoDash to:

  • Track the active provider.
  • Detect stale providers.
  • Handle application switching.
  • Resolve multiple providers.
  • Display diagnostic information.
  • Prevent unrelated tweaks from accidentally overwriting each other’s state.

Data lifetime

A third-party tweak should explicitly distinguish between:

  • Valid current data.
  • Temporarily unavailable data.
  • Stale data.
  • Provider disconnected.
  • Application terminated.

A provider must not leave an old speed value active indefinitely after its application has stopped producing information. A stale number on a dashboard is worse than no number, because the driver has no way to tell it is stale.

App running:
72 km/h

App stops producing speed:
INVALID / unavailable

App terminated:
Provider disconnected

DuoDash may additionally implement a timeout mechanism to invalidate stale provider data.

Update frequency

Providers should avoid sending unnecessarily high-frequency updates. For UI information such as speed, update only when:

  • The value changes.
  • The data becomes invalid.
  • The unit changes.
  • The source state changes.
  • A meaningful update interval has elapsed.

Do not send updates every display frame. Excessive updates waste CPU time and may negatively affect both the iPhone and the CarPlay environment.

Full integration example

A complete conceptual integration, showing availability checks, registration, the invalid-data path and teardown:

// PSEUDOCODE — NOT FINAL DUODASH API

@interface ExampleSpeedProvider : NSObject
@end

@implementation ExampleSpeedProvider

- (void)start
{
    if (!DDIsAvailable()) {
        return;
    }

    if (!DDCapabilityAvailable(@"navigation-bubble")) {
        return;
    }

    DDRegisterProvider(@"com.example.speedprovider");

    [self startObservingApplicationSpeed];
}

- (void)applicationSpeedChanged:(double)speed
{
    if (speed < 0) {
        DDNavigationSetUnavailable(
            @"com.example.speedprovider"
        );
        return;
    }

    DDNavigationUpdateSpeed(
        @"com.example.speedprovider",
        speed,
        DDSpeedUnitKPH
    );
}

- (void)stop
{
    DDNavigationSetUnavailable(
        @"com.example.speedprovider"
    );

    DDUnregisterProvider(
        @"com.example.speedprovider"
    );
}

@end

All DD* symbols shown above are placeholders.

API reference

To be published when the DuoDash Developer API is finalised. It will cover the Navigation Bubble header, provider registration, the speed update call, invalidating data and unregistering.

Not yet available. Get in touch to be told when it is published.

Next: registering a tweak, provider lifecycle and the release checklist →