public class LocationButton

  1. Object
  2. Component
  3. Container
  4. LocationButton

ImplementsAnimation, Editable, Iterable<Component>, StyleListener

A button that asks for the device location once, for a single transaction.

This is the Codename One face of the platform’s own location button. From Android 17 (API level 37) Google Play requires transactional precise-location use – “find restaurants near me”, filling in an address, tagging a photo – to go through a button the system draws, rather than through an app-held ACCESS_FINE_LOCATION grant. A tap on a button the system drew earns a session-scoped grant, so the application never has to hold precise location permanently.

LocationButton b = new LocationButton(LocationButton.TEXT_USE_PRECISE_LOCATION);
b.addLocationSharedListener(loc -> {
    if (loc != null) {
        search(loc.getLatitude(), loc.getLongitude());
    }
});
form.add(b);

Where the system draws it, and where it does not

On a platform that has such a control – today only Android 17 and up – this component is that control: it is rendered by the system in its own process and this application cannot restyle its label or intercept its taps, which is exactly what makes the grant trustworthy. Everywhere else, and on older Android, the component is an ordinary Codename One Button that asks for the location permission the usual way. Either way the listener receives a Location or null, so an application is written once.

isSystemRendered() reports which of the two this button ended up with, for an application that wants to say something different about it. Ask com.codename1.ui.Display#isLocationButtonSupported() instead when the question is what the platform can do rather than what happened here.

On Android

Referencing this class makes the build add USE_LOCATION_BUTTON to the manifest, which the platform requires before it will render the control. Nothing else is needed.

The build also decides how to declare ACCESS_FINE_LOCATION. An application that uses this component and nothing else from the location or maps packages gets it declared onlyForLocationButton, which means the system grants precise location through the button and never any other way – no “allow precise location” question, and nothing to justify to Google Play. An application that also tracks, navigates or geofences needs the ordinary grant and gets the ordinary declaration. The class scan the build already runs answers this, so neither case needs a build hint.

android.locationButton.exclusive (auto, true, false) overrides it, for an application whose location use that scan cannot see – native Android code reaching the platform’s own location APIs is the case that matters. Writing the declaration by hand through android.xpermissions is not the way to ask for it: the build cannot check a hand-written fragment against the compile SDK, and onlyForLocationButton is an API 37 value that AAPT rejects below it.

Fields

public static final int TEXT_NONE = 0An icon with no label.
public static final int TEXT_PRECISE_LOCATION = 1Labelled “Precise location”.
public static final int TEXT_USE_PRECISE_LOCATION = 2Labelled “Use precise location”.
public static final int TEXT_SHARE_PRECISE_LOCATION = 3Labelled “Share precise location”.
public static final int TEXT_NEAR_MY_PRECISE_LOCATION = 4Labelled “Near my precise location”.
public static final int TEXT_NEAR_YOUR_PRECISE_LOCATION = 5Labelled “Near your precise location”.

Constructors

public LocationButton()A button labelled “Use precise location”.
public LocationButton(int textType)A button with one of the labels the platform offers.

Methods

public boolean isSystemRendered()Whether a tap on this button goes through a control the system itself drew.
public int getTextType()The label this button carries.
public void setTextType(int textType)Chooses the label this button carries.
public void setButtonBackgroundColor(int color)Asks the platform to draw the button on this background colour.
public int getButtonBackgroundColor()The background colour asked of the platform, or -1.
public void setButtonTextColor(int color)Asks the platform to draw the button’s label in this colour.
public int getButtonTextColor()The label colour asked of the platform, or -1.
public long getTimeout()How long to wait for a fix once the request has been granted.
public void setTimeout(long timeout)How long to wait for a fix once the request has been granted.
public void addLocationSharedListener(LocationSharedListener l)Registers a listener for the location this button obtains.
public void removeLocationSharedListener(LocationSharedListener l)Removes a previously registered listener.
protected Dimension calcPreferredSize()The size an ordinary themed button with the same label would have, but never below the platform’s minimum touch target.
protected void initComponent()Allows subclasses to bind functionality that relies on fully initialized and “ready for action” component state

Inherited fields

Inherited methods

From Container

encloseIn, encloseIn, initLaf, getUIManager, setUIManager, isSurface, add, addAll, add, add, add, add, add, getLeadComponent, setLeadComponent, getLeadParent, keyPressed, keyReleased, getLayout, setLayout, invalidate, setShouldLayout, setShouldCalcPreferredSize, getLayoutWidth, getLayoutHeight, applyRTL, constrainWidthWhenScrollable, constrainHeightWhenScrollable, addComponent, addComponent, addComponent, addComponent, replaceAndWait, replaceAndWait, replace, replaceAndWait, replace, createReplaceTransition, isEnabled, setEnabled, removeComponent, cancelRepaints, flushReplace, removeAll, revalidateWithAnimationSafety, revalidate, revalidateLater, forceRevalidate, clearClientProperties, paint, paintGlass, layoutContainer, isSafeArea, setSafeArea, isSafeAreaRoot, getSafeAreaRoot, setSafeAreaRoot, getComponentCount, getComponentAt, getComponentIndex, contains, scrollComponentToVisible, getClosestComponentTo, getResponderAt, getComponentAt, findDropTargetAt, pointerPressed, paramString, refreshTheme, isScrollableX, setScrollableX, isScrollableY, setScrollableY, getSideGap, getBottomGap, setScrollable, setCellRenderer, getScrollIncrement, setScrollIncrement, findFirstFocusable, dragInitiated, fireClicked, isSelectableInteraction, getGridPosY, paintComponentBackground, getGridPosX, animateHierarchyAndWait, createAnimateHierarchy, animateHierarchy, animateHierarchyFadeAndWait, createAnimateHierarchyFade, animateHierarchyFade, animateLayoutFadeAndWait, createAnimateLayoutFadeAndWait, animateLayoutFade, createAnimateLayoutFade, animateLayoutAndWait, animateLayout, updateTabIndices, createAnimateLayout, drop, createAnimateMotion, morph, morphAndWait, animateUnlayout, animateUnlayoutAndWait, createAnimateUnlayout, getChildrenAsList, iterator, iterator

From Component

setSameSize, isSetCursorSupported, parsePreferredSize, getDefaultDragTransparency, setDefaultDragTransparency, getEditingDelegate, setEditingDelegate, getCursor, setCursor, showNativeOverlay, hideNativeOverlay, updateNativeOverlay, getNativeOverlay, getAllStyles, getSameWidth, setSameWidth, getSameHeight, setSameHeight, getX, setX, getOuterX, getInnerX, getY, setY, getOuterY, getInnerY, isVisible, setVisible, getClientProperty, stripMarginAndPadding, putClientProperty, getDirtyRegion, setDirtyRegion, isOpaque, setOpaque, getWidth, setWidth, getOuterWidth, getInnerWidth, getHeight, setHeight, getOuterHeight, getInnerHeight, isDragRegion, getDragRegionStatus, getBaseline, getBaselineResizeBehavior, getPreferredSizeStr, setPreferredSizeStr, getPreferredSize, setPreferredSize, getScrollDimension, calcScrollSize, setScrollSize, getPreferredW, setPreferredW, getPreferredH, setPreferredH, getOuterPreferredH, getInnerPreferredH, getOuterPreferredW, getInnerPreferredW, setSize, getUIID, setUIID, setUIIDFinal, setUIID, getInlineAllStyles, setInlineAllStyles, getInlineSelectedStyles, setInlineSelectedStyles, getInlineUnselectedStyles, setInlineUnselectedStyles, getInlineDisabledStyles, setInlineDisabledStyles, getInlinePressedStyles, setInlinePressedStyles, remove, getParent, getOwner, setOwner, isOwnedBy, containsOrOwns, addFocusListener, removeFocusListener, addScrollListener, removeScrollListener, getSelectCommandText, setSelectCommandText, getLabelForComponent, setLabelForComponent, focusGained, focusLost, paintBackgrounds, paintShadows, getAbsoluteX, getAbsoluteY, isInClippingRegion, paintIntersectingComponentsAbove, paintScrollbars, paintScrollbarX, getScrollOpacity, getSelectedRect, paintScrollbarY, paintComponent, paintComponent, getBorder, getScrollable, paintBackground, isScrollable, getScrollX, setScrollX, getScrollY, setScrollY, onScrollX, onScrollY, getDraggedx, getDraggedy, contains, visibleBoundsContains, hasFixedPreferredSize, getBounds, getBounds, getVisibleBounds, getVisibleBounds, isFocusable, setFocusable, onSetFocusable, resetFocusable, getTabIndex, setTabIndex, getPreferredTabIndex, setPreferredTabIndex, isTraversable, setTraversable, handlesInput, setHandlesInput, consumesRawTextInput, hasFocus, setFocus, getComponentForm, getTopLevelContainer, repaint, repaint, longKeyPress, keyRepeated, registerForAnimation, deregisterFromAnimation, getAnimationManager, getScrollAnimationSpeed, setScrollAnimationSpeed, isBlockLead, setBlockLead, isIgnorePointerEvents, setIgnorePointerEvents, isRippleEffect, setRippleEffect, getInlineStylesTheme, setInlineStylesTheme, shouldRenderComponentSelection, isHideInLandscape, setHideInLandscape, createStyleAnimation, isSmoothScrolling, setSmoothScrolling, pointerHover, stopScrollMomentum, pointerHoverReleased, pointerHoverPressed, pinch, pinchReleased, pinch, rotation, isPinchBlocksDragAndDrop, setPinchBlocksDragAndDrop, pointerDragged, getDragImage, getDragTransparency, setDragTransparency, toImage, drawDraggedImage, draggingOver, dragEnter, dragExit, addPullToRefresh, setPullToRefresh, respondsToPointerEvents, pointerDragged, isStickyDrag, pointerPressed, isDragAndDropOperation, pointerReleased, longPointerPress, pointerReleased, setVerticalScrollBounds, setHorizontalScrollBounds, isVScrollThumbGrabbed, isHScrollThumbGrabbed, isVScrollThumbHover, isHScrollThumbHover, isTensileDragEnabled, setTensileDragEnabled, getTextSelectionSupport, addDropListener, removeDropListener, addDragOverListener, removeDragOverListener, isNativeDragSource, setNativeDragSource, getNativeDragOperation, setNativeDragOperation, createNativeDragOperation, isNativeDropTarget, setNativeDropTarget, getAcceptedDropMimeTypes, setAcceptedDropMimeTypes, getAcceptedDropActions, setAcceptedDropActions, canAcceptNativeDrop, nativeDragEnter, nativeDragOver, nativeDragExit, nativeDrop, addNativeDropListener, removeNativeDropListener, addNativeDragOverListener, removeNativeDragOverListener, dragFinished, addDragFinishedListener, addStateChangeListener, removeStateChangeListener, addPointerPressedListener, addLongPressListener, addContextMenuListener, removeContextMenuListener, addMouseWheelListener, removeMouseWheelListener, addStylusListener, removeStylusListener, mouseWheel, paintRippleOverlay, removePointerPressedListener, removeLongPressListener, removeDragFinishedListener, addPointerReleasedListener, removePointerReleasedListener, addPointerDraggedListener, removePointerDraggedListener, getDragSpeed, getStyle, getPressedStyle, setPressedStyle, initUnselectedStyle, initPressedStyle, initDisabledStyle, initSelectedStyle, getUnselectedStyle, setUnselectedStyle, getSelectedStyle, setSelectedStyle, getDisabledStyle, setDisabledStyle, installDefaultPainter, requestFocus, toString, refreshTheme, refreshTheme, isDragActivated, animate, scrollRectToVisible, scrollRectToVisible, paintBorder, paintBorderBackground, isCellRenderer, isScrollVisible, setScrollVisible, setIsScrollVisible, startEditingAsync, stopEditing, isEditing, isEditable, laidOut, deinitialize, isInitialized, setInitialized, styleChanged, getNextFocusDown, setNextFocusDown, getNextFocusUp, setNextFocusUp, getNextFocusLeft, setNextFocusLeft, getNextFocusRight, setNextFocusRight, getName, setName, initCustomStyle, deinitializeCustomStyle, isRTL, setRTL, isTactileTouch, isTactileTouch, setTactileTouch, getPropertyNames, getPropertyTypes, getPropertyTypeNames, getPropertyValue, setPropertyValue, paintLockRelease, paintLock, isSnapToGrid, setSnapToGrid, shouldBlockSideSwipe, shouldBlockSideSwipeLeft, shouldBlockSideSwipeRight, blocksSideSwipe, isFlatten, setFlatten, getTensileLength, setTensileLength, isGrabsPointerEvents, setGrabsPointerEvents, getScrollOpacityChangeSpeed, setScrollOpacityChangeSpeed, growShrink, isAlwaysTensile, setAlwaysTensile, isDraggable, setDraggable, isDropTarget, setDropTarget, isChildOf, isHideInPortrait, setHideInPortrait, getBindablePropertyNames, getBindablePropertyTypes, bindProperty, unbindProperty, getBoundPropertyValue, setBoundPropertyValue, getCloudBoundProperty, setCloudBoundProperty, getCloudDestinationProperty, setCloudDestinationProperty, getComponentState, setComponentState, setHidden, isHidden, setHidden, isHidden, announceForAccessibility, getAccessibilityText, setAccessibilityText, getSemantics, getAccessibilityNode, accessibilityChanged, accessibilityChanged, getTooltip, setTooltip

Field details

TEXT_NONE

public static final int TEXT_NONE = 0
An icon with no label. The narrowest form of the control.

TEXT_PRECISE_LOCATION

public static final int TEXT_PRECISE_LOCATION = 1
Labelled “Precise location”.

TEXT_USE_PRECISE_LOCATION

public static final int TEXT_USE_PRECISE_LOCATION = 2
Labelled “Use precise location”. The default.

TEXT_SHARE_PRECISE_LOCATION

public static final int TEXT_SHARE_PRECISE_LOCATION = 3
Labelled “Share precise location”.

TEXT_NEAR_MY_PRECISE_LOCATION

public static final int TEXT_NEAR_MY_PRECISE_LOCATION = 4
Labelled “Near my precise location”.

TEXT_NEAR_YOUR_PRECISE_LOCATION

public static final int TEXT_NEAR_YOUR_PRECISE_LOCATION = 5
Labelled “Near your precise location”.

Constructor details

LocationButton

public LocationButton()
A button labelled “Use precise location”.

LocationButton

public LocationButton(int textType)
A button with one of the labels the platform offers.

Parameters

textType int
one of the TEXT_ constants

Throws

IllegalArgumentException
if textType is not one of them

Method details

isSystemRendered

public boolean isSystemRendered()

Whether a tap on this button goes through a control the system itself drew.

False means this component is not showing the system’s control: every platform other than Android, Android below API level 37, before the component has been shown, in the moment between the control being created and the system opening its session, and on a device where the platform HAS the control but its session failed and useFallback() replaced it.

That last case is why this is an instance question rather than a static one. Display.isLocationButtonSupported() answers what the platform can do and is the right call to make before building anything; only the component knows what actually ended up on screen.

Returns

whether the system drew the control this button is showing

getTextType

public int getTextType()
The label this button carries.

Returns

one of the TEXT_ constants

setTextType

public void setTextType(int textType)
Chooses the label this button carries.

Parameters

textType int
one of the TEXT_ constants

Throws

IllegalArgumentException
if textType is not one of them

setButtonBackgroundColor

public void setButtonBackgroundColor(int color)

Asks the platform to draw the button on this background colour.

Only reaches the system-rendered control; the fallback button is themed through its LocationButton UIID like any other component.

Parameters

color int
an RRGGBB colour, or -1 to let the system choose

getButtonBackgroundColor

public int getButtonBackgroundColor()
The background colour asked of the platform, or -1.

Returns

an RRGGBB colour or -1

setButtonTextColor

public void setButtonTextColor(int color)
Asks the platform to draw the button’s label in this colour.

Parameters

color int
an RRGGBB colour, or -1 to let the system choose

getButtonTextColor

public int getButtonTextColor()
The label colour asked of the platform, or -1.

Returns

an RRGGBB colour or -1

getTimeout

public long getTimeout()
How long to wait for a fix once the request has been granted.

Returns

the timeout in milliseconds, or -1 to wait indefinitely

setTimeout

public void setTimeout(long timeout)

How long to wait for a fix once the request has been granted.

A cold GPS fix is legitimately slow, so this is deliberately generous; on expiry the listener is invoked with null rather than left hanging.

Parameters

timeout long
milliseconds, or -1 to wait indefinitely

addLocationSharedListener

public void addLocationSharedListener(LocationSharedListener l)
Registers a listener for the location this button obtains.

Parameters

l LocationSharedListener
the listener

removeLocationSharedListener

public void removeLocationSharedListener(LocationSharedListener l)
Removes a previously registered listener.

Parameters

l LocationSharedListener
the listener

calcPreferredSize

protected Dimension calcPreferredSize()

The size an ordinary themed button with the same label would have, but never below the platform’s minimum touch target.

The system-rendered control is given whatever size we ask for, so this answer is used for both paths and the two look alike. The floor is not a nicety: Android clamps a location button up to 48dp and says so in the log (“Clamping height up from 60 to 126 px”), and the button it then draws overflows the slot Codename One laid out for it – observed on an Android 17 emulator, where the control was visibly cut in half.

Returns

the preferred size

initComponent

protected void initComponent()
Allows subclasses to bind functionality that relies on fully initialized and “ready for action” component state