public class 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 = 0 | An icon with no label. |
public static final int TEXT_PRECISE_LOCATION = 1 | Labelled “Precise location”. |
public static final int TEXT_USE_PRECISE_LOCATION = 2 | Labelled “Use precise location”. |
public static final int TEXT_SHARE_PRECISE_LOCATION = 3 | Labelled “Share precise location”. |
public static final int TEXT_NEAR_MY_PRECISE_LOCATION = 4 | Labelled “Near my precise location”. |
public static final int TEXT_NEAR_YOUR_PRECISE_LOCATION = 5 | Labelled “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
From Component
DEFAULT_CURSOR, CROSSHAIR_CURSOR, TEXT_CURSOR, WAIT_CURSOR, SW_RESIZE_CURSOR, SE_RESIZE_CURSOR, NW_RESIZE_CURSOR, NE_RESIZE_CURSOR, N_RESIZE_CURSOR, S_RESIZE_CURSOR, W_RESIZE_CURSOR, E_RESIZE_CURSOR, HAND_CURSOR, MOVE_CURSOR, DRAG_REGION_NOT_DRAGGABLE, DRAG_REGION_POSSIBLE_DRAG_X, DRAG_REGION_POSSIBLE_DRAG_Y, DRAG_REGION_POSSIBLE_DRAG_XY, DRAG_REGION_LIKELY_DRAG_X, DRAG_REGION_LIKELY_DRAG_Y, DRAG_REGION_LIKELY_DRAG_XY, DRAG_REGION_IMMEDIATELY_DRAG_X, DRAG_REGION_IMMEDIATELY_DRAG_Y, DRAG_REGION_IMMEDIATELY_DRAG_XY, BRB_CONSTANT_ASCENT, BRB_CONSTANT_DESCENT, BRB_CENTER_OFFSET, BRB_OTHER, CENTER, TOP, LEFT, BOTTOM, RIGHT, BASELINE
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 = 0TEXT_PRECISE_LOCATION
public static final int TEXT_PRECISE_LOCATION = 1TEXT_USE_PRECISE_LOCATION
public static final int TEXT_USE_PRECISE_LOCATION = 2TEXT_SHARE_PRECISE_LOCATION
public static final int TEXT_SHARE_PRECISE_LOCATION = 3TEXT_NEAR_MY_PRECISE_LOCATION
public static final int TEXT_NEAR_MY_PRECISE_LOCATION = 4TEXT_NEAR_YOUR_PRECISE_LOCATION
public static final int TEXT_NEAR_YOUR_PRECISE_LOCATION = 5Constructor details
LocationButton
public LocationButton()LocationButton
public LocationButton(int textType)Parameters
textTypeint- one of the
TEXT_constants
Throws
IllegalArgumentException- if
textTypeis 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
getTextType
public int getTextType()Returns
TEXT_ constantssetTextType
public void setTextType(int textType)Parameters
textTypeint- one of the
TEXT_constants
Throws
IllegalArgumentException- if
textTypeis 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
colorint- an RRGGBB colour, or -1 to let the system choose
getButtonBackgroundColor
public int getButtonBackgroundColor()Returns
setButtonTextColor
public void setButtonTextColor(int color)Parameters
colorint- an RRGGBB colour, or -1 to let the system choose
getButtonTextColor
public int getButtonTextColor()Returns
getTimeout
public long getTimeout()Returns
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
timeoutlong- milliseconds, or -1 to wait indefinitely
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
initComponent
protected void initComponent()