Class LocationButton

All Implemented Interfaces:
Animation, Editable, StyleListener, Iterable<Component>

public class LocationButton extends Container

A button the user taps to share their precise location once.

This is the transactional half of the location API: a "find shops near me" button, an address auto-fill, a one-time "share where I am". It is not a replacement for LocationManager, which stays the right API for navigation, tracking, geofencing and anything else that follows the device over time.

The distinction is not cosmetic. Where the platform draws a location button of its own, this component uses it, and a tap grants precise location for that session only -- the app never holds a persistent grant, and the user is never asked again on the next tap. Where the platform has no such control the component is an ordinary Codename One button that asks for location the usual way, so the same code compiles and runs everywhere.

LocationButton share = new LocationButton(LocationButton.TEXT_SHARE_PRECISE_LOCATION);
share.addLocationSharedListener(loc -> {
    if (loc == null) {
        status.setText("Location not shared");
    } else {
        status.setText(loc.getLatitude() + ", " + loc.getLongitude());
    }
    status.getParent().revalidate();
});
form.add(share);
Android and Google Play

Google Play requires the system-rendered location button for transactional precise-location use in apps targeting Android 17 (API 37) and later; a persistent ACCESS_FINE_LOCATION grant is reserved for core functionality and carries a Play Console declaration. Referencing this class is what makes the Android build declare USE_LOCATION_BUTTON and add the platform library, so the button is system-rendered on API 37 and later and falls back to the standard permission prompt below it.

An app whose only use of precise location is this button should also set the android.locationButton.exclusive=true build hint. That marks ACCESS_FINE_LOCATION as reachable through the button alone (usesPermissionFlags="onlyForLocationButton"), which is what removes the need for the persistent-location declaration. Do not set it in an app that also tracks, navigates or geofences: those calls would then be refused the grant they need.

Other platforms

iOS has no system-rendered button, but its own permission dialog offers "Allow Once", which is the same session-scoped grant reached a different way; the fallback button is the correct behaviour there. The simulator and every other port behave the same way.

  • Field Details

    • TEXT_NONE

      public static final int TEXT_NONE
      No label -- the location icon alone.
      See Also:
    • TEXT_PRECISE_LOCATION

      public static final int TEXT_PRECISE_LOCATION
      Labelled "Precise location". The default.
      See Also:
    • TEXT_USE_PRECISE_LOCATION

      public static final int TEXT_USE_PRECISE_LOCATION
      Labelled "Use precise location".
      See Also:
    • TEXT_SHARE_PRECISE_LOCATION

      public static final int TEXT_SHARE_PRECISE_LOCATION
      Labelled "Share precise location".
      See Also:
    • TEXT_NEAR_MY_PRECISE_LOCATION

      public static final int TEXT_NEAR_MY_PRECISE_LOCATION
      Labelled "Near my precise location".
      See Also:
    • TEXT_NEAR_YOUR_PRECISE_LOCATION

      public static final int TEXT_NEAR_YOUR_PRECISE_LOCATION
      Labelled "Near your precise location".
      See Also:
  • Constructor Details

    • LocationButton

      public LocationButton()
      Creates a button labelled "Precise location".
    • LocationButton

      public LocationButton(int textType)

      Creates a button with the given label.

      Parameters
      • textType: one of the TEXT_ constants
  • Method Details

    • isSystemRendered

      public static boolean isSystemRendered()

      True when this device draws the button itself, which is what makes the grant session-scoped.

      Useful for explanatory copy -- there is nothing to branch on otherwise, since the component works either way.

      Returns

      whether a tap goes through the system's own button

    • getTextType

      public int getTextType()

      The label the button carries.

      Returns

      one of the TEXT_ constants

    • setTextType

      public void setTextType(int textType)

      Sets the label the button carries.

      Parameters
      • textType: one of the TEXT_ constants
    • setButtonBackgroundColor

      public void setButtonBackgroundColor(int color)

      Overrides the button's background colour.

      Left alone by default, which is deliberate: a location button the user recognises is the point of the control, and the system's own colours are what make it recognisable. Restyle only when the default is unreadable against the surface it sits on.

      Parameters
      • color: an RRGGBB colour, or -1 to restore the platform's own
    • getButtonBackgroundColor

      public int getButtonBackgroundColor()
      The background colour override, or -1 when the platform's own is used.
    • setButtonTextColor

      public void setButtonTextColor(int color)

      Overrides the button's text and icon colour. See setButtonBackgroundColor(int) on why the default is worth keeping.

      Parameters
      • color: an RRGGBB colour, or -1 to restore the platform's own
    • getButtonTextColor

      public int getButtonTextColor()
      The text colour override, or -1 when the platform's own is used.
    • getTimeout

      public long getTimeout()

      How long to wait for a fix after the grant, in milliseconds.

      Returns

      the timeout, or -1 to wait indefinitely

    • setTimeout

      public void setTimeout(long timeout)

      Sets how long to wait for a fix after the grant.

      The default is 30 seconds. Waiting indefinitely is available but rarely what a transactional flow wants: a first GPS fix indoors can never arrive, and the listener would then never be called at all.

      Parameters
      • timeout: milliseconds, or -1 to wait indefinitely
    • addLocationSharedListener

      public void addLocationSharedListener(LocationSharedListener l)

      Adds a listener for the location this button obtains.

      Parameters
      • l: the listener
    • removeLocationSharedListener

      public void removeLocationSharedListener(LocationSharedListener l)

      Removes a previously added listener.

      Parameters
      • l: the listener
    • isUnavailable

      public boolean isUnavailable()

      True when the platform's button was drawn and then failed, so this component cannot obtain a location at all.

      A failed session leaves nothing usable: see systemButtonFailed() on why substituting an ordinary permission request would be wrong rather than merely worse. The component shows a disabled placeholder so the layout does not jump; an app that would rather show its own message can ask this and replace the component.

      Returns

      whether this button has become unusable