Class Geolocation
- All Implemented Interfaces:
Serializable
UI.getGeolocation().
Every entry point on this class is asynchronous: calling it enqueues a request to the browser and returns immediately. The browser answers later (after the user responds to a permission prompt, after the operating system reports a position, or after a timeout), and Flow invokes the callback or updates the signal on the UI thread.
Two usage modes:
get(SerializableConsumer, SerializableConsumer)— one-shot position request. Use this when the application only needs to know the user's location at a single moment (e.g. on a button click). Takes a pair of callbacks — one for a successfulGeolocationPosition, one for aGeolocationError— mirroring the W3CgetCurrentPosition(success, error)pair and matchingGeolocationTracker.addPositionListener. An overload accepts a trailingGeolocationOptionsfor accuracy / timeout / cache-age tuning.track(Component)— continuous tracking that keeps the server updated as the user moves. Returns aGeolocationTrackerwhosevalueSignal()is a reactive signal ofGeolocationResult. The browser watch is automatically cancelled when the owning component detaches; useGeolocationTracker.stop()to cancel it sooner andGeolocationTracker.resume()to resume.
availabilitySignal()— reactive signal of whether the feature is usable and what permission state the origin has. Subscribe withSignal.effect(owner, ...)to react to changes, or callavailabilitySignal().peek()for a snapshot.
Permission prompts. The first time the application asks for a
location, the browser shows its own permission dialog. The dialog is
controlled by the browser, not by Flow — Flow cannot style it, suppress it,
or detect when it is shown. If the user denies the prompt the callback
receives a GeolocationError whose errorCode is GeolocationErrorCode.PERMISSION_DENIED.
One-shot example:
Button locate = new Button("Use my location");
locate.addClickListener(
e -> e.getUI().getGeolocation()
.get(pos -> showNearest(pos.coords().latitude(),
pos.coords().longitude()),
err -> showManualEntry()));
Tracking example:
GeolocationTracker tracker = UI.getCurrent().getGeolocation().track(this);
Signal.effect(this, () -> {
switch (tracker.valueSignal().get()) {
case GeolocationPending p -> {
// waiting for first reading
}
case GeolocationPosition pos ->
map.setCenter(new Coordinate(pos.coords().longitude(),
pos.coords().latitude()));
case GeolocationError err -> showError(err.message());
}
});
- See Also:
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionReturns a read-only signal holding the current geolocation availability — whether the Geolocation API is usable in this context and, if so, what permission state the origin has.voidget(SerializableConsumer<GeolocationPosition> onSuccess, SerializableConsumer<GeolocationError> onError) Requests the user's current position once.voidget(SerializableConsumer<GeolocationPosition> onSuccess, SerializableConsumer<GeolocationError> onError, @Nullable GeolocationOptions options) Requests the user's current position once with tuning options.Starts continuously watching the user's position, tied to the owner component's lifecycle.track(Component owner, @Nullable GeolocationOptions options) Starts continuously watching the user's position with tuning options, tied to the owner component's lifecycle.
-
Constructor Details
-
Geolocation
Creates a new Geolocation facade bound to the given UI.Framework-only. Application code obtains the instance via
UI.getGeolocation()and should not instantiate this class directly — attempting to create a second instance for a UI that already has one throws.The underlying
GeolocationClientis resolved throughLookup: if aGeolocationClientFactoryis registered, itsGeolocationClientFactory.create(UI)produces the client. Otherwise the built-in browser-backed client is used.- Parameters:
ui- the UI this facade belongs to- Throws:
IllegalStateException- if the UI already has a Geolocation facade
-
-
Method Details
-
get
public void get(SerializableConsumer<GeolocationPosition> onSuccess, SerializableConsumer<GeolocationError> onError) Requests the user's current position once. On a successful readingonSuccessis invoked with theGeolocationPosition; if the browser reports an error insteadonErroris invoked with theGeolocationError. The pair mirrors the W3CgetCurrentPosition(success, error)signature and matchesGeolocationTracker.addPositionListener, so callers can share the same handler shape between one-shot and watch APIs.The call returns immediately. The browser may show a permission dialog on the first call; after the user responds, exactly one of the callbacks is invoked on the UI thread.
- Parameters:
onSuccess- invoked with the position on a successful reading; notnullonError- invoked with the error if the browser reports one; notnull
-
get
public void get(SerializableConsumer<GeolocationPosition> onSuccess, SerializableConsumer<GeolocationError> onError, @Nullable GeolocationOptions options) Requests the user's current position once with tuning options. Use this to trade accuracy for battery/speed or to accept a recent cached reading. SeeGeolocationOptionsfor the available settings.The call returns immediately. The browser may show a permission dialog on the first call; after the user responds, exactly one of the callbacks is invoked on the UI thread.
- Parameters:
onSuccess- invoked with the position on a successful reading; notnullonError- invoked with the error if the browser reports one; notnulloptions- accuracy / timeout / cache-age tuning, ornullto use the browser defaults
-
track
Starts continuously watching the user's position, tied to the owner component's lifecycle.The browser reports new positions whenever it detects movement. Each report is delivered to the returned tracker's
valueSignal()signal on the UI thread. The initial value isGeolocationPendinguntil the first reading arrives, then transitions toGeolocationPosition(updated on every subsequent reading) orGeolocationError.The underlying browser watch is automatically cancelled when
ownerdetaches, so the application does not need to write cleanup code for navigation. For cancelling while the view is still attached (e.g. a "Stop tracking" button), callGeolocationTracker.stop()on the returned tracker.Permission-revoke caveat. If the user revokes geolocation permission while a watch is active and then grants it again, the browser silently stops delivering position updates to the existing watch — this is the W3C Geolocation API's documented behavior across browsers, not a Flow-specific limitation. To recover after a revoke/regrant cycle, call
GeolocationTracker.stop()followed byGeolocationTracker.resume(), which installs a fresh browser watch. Applications that want this to happen automatically can subscribe toavailabilitySignal()withSignal.effect(owner, ...)and trigger the stop/resume when the availability transitions back toGRANTED.- Parameters:
owner- the component that owns this tracking session; detaching the component automatically stops the watch- Returns:
- a tracker whose
GeolocationTracker.valueSignal()reports progress and whoseGeolocationTracker.stop()cancels the watch
-
track
Starts continuously watching the user's position with tuning options, tied to the owner component's lifecycle. Behaves liketrack(Component)but lets the caller request high accuracy, set a failure timeout, or accept cached readings. SeeGeolocationOptionsfor the available settings.- Parameters:
owner- the component that owns this tracking session; detaching the component automatically stops the watchoptions- accuracy / timeout / cache-age tuning, ornullto use the browser defaults- Returns:
- a tracker whose
GeolocationTracker.valueSignal()reports progress and whoseGeolocationTracker.stop()cancels the watch
-
availabilitySignal
Returns a read-only signal holding the current geolocation availability — whether the Geolocation API is usable in this context and, if so, what permission state the origin has.Subscribe with
Signal.effect(owner, ...)to react to availability changes (e.g. disabling a location button when the user revokes permission). For a snapshot read, callavailabilitySignal().peek(); in an effect or reactive context, callavailabilitySignal().get().The signal starts as
UNKNOWN, transitions to the value reported during the initial client bootstrap, and updates on everyget(com.vaadin.flow.function.SerializableConsumer<com.vaadin.flow.component.geolocation.GeolocationPosition>, com.vaadin.flow.function.SerializableConsumer<com.vaadin.flow.component.geolocation.GeolocationError>)/track(com.vaadin.flow.component.Component)outcome and on browser permission-change events where supported.Reliability caveats. The value is best-effort, not authoritative — it reflects what the browser last reported, and can be briefly stale in these cases:
- Between server attach and the completion of the first client
handshake — holds
UNKNOWNduring this short window, indistinguishable from a real UNKNOWN reported by the browser. - On Safari, the permission state is never observable;
GRANTED,DENIEDandPROMPTall surface asUNKNOWN.UNSUPPORTEDis still reported correctly. - On Firefox, permission changes the user makes in browser settings are
not reliably propagated back — the signal can stay stale until the next
get(com.vaadin.flow.function.SerializableConsumer<com.vaadin.flow.component.geolocation.GeolocationPosition>, com.vaadin.flow.function.SerializableConsumer<com.vaadin.flow.component.geolocation.GeolocationError>)ortrack(com.vaadin.flow.component.Component)call. - On Chromium, the value updates promptly when the user flips the site permission, but there is still a small propagation delay between the browser event and the cache update.
get(com.vaadin.flow.function.SerializableConsumer<com.vaadin.flow.component.geolocation.GeolocationPosition>, com.vaadin.flow.function.SerializableConsumer<com.vaadin.flow.component.geolocation.GeolocationError>)and handle the authoritative result in the callback.- Returns:
- the availability signal
- Between server attach and the completion of the first client
handshake — holds
-