public class PhoneVerification

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

ImplementsAnimation, Editable, Iterable<Component>, StyleListener

The two stages of verifying that a user holds a phone number: enter the number, then enter the code that arrives by SMS.

The application supplies both server calls. This component owns everything around them: the number entry, the code entry, the wait before a resend is offered, the way back to a mistyped number, and the errors either call reports.

Example

PhoneVerification verify = new PhoneVerification();
verify.setCodeSender((number, response) -> myServer.sendSms(number, response));
verify.setCodeVerifier((number, code, response) -> myServer.check(number, code, response));
verify.addVerifiedListener(e -> showMainScreen());
form.add(verify);

A sender is handed the number and a Response, and calls exactly one of Response#succeeded() or Response#failed(String) when its server answers – from any thread. Until then the button it came from stays disabled, so a second tap cannot send a second message.

The code is offered by the platform

The code field is an OtpField, so it carries the one-time-code hint and the platform offers the arriving code on the keyboard or through autofill. Nothing here reads messages, and no messaging permission is involved.

Styling

The component uses the UIID “PhoneVerification”, its explanatory lines “PhoneVerificationText”, its error line “PhoneVerificationError” and its buttons “PhoneVerificationButton” – except the resend and change-number buttons, which use “PhoneVerificationLink”.

Nested types

class PhoneVerification.ResponseThe application’s answer to one request.
interface PhoneVerification.CodeSenderAsks the application’s server to send a code to a number.
interface PhoneVerification.CodeVerifierAsks the application’s server whether a code matches a number.

Constructors

public PhoneVerification()Builds the flow with a six digit code.
public PhoneVerification(int codeLength)Builds the flow with a code of the given length.

Methods

public void showNumberStage()Returns to the first stage, with the number as it was left, and clears any code that was typed.
public void showCodeStage(String e164Number)Moves to the code stage for a number, as though the code had just been sent.
public boolean isCodeStage()True when the code stage is showing.
public void requestCode(String e164Number)Sends a code to a number, moving to the code stage when the server accepts it.
public static boolean isPlausibleE164(String e164Number)The shape a number must have before a request is worth making: a “+”, then between five and fifteen digits, which is what E.164 allows.
public void submitCode()Verifies the code currently entered.
protected void deinitialize()Invoked to indicate that the component initialization is being reversed since the component was detached from the container hierarchy.
protected void initComponent()Allows subclasses to bind functionality that relies on fully initialized and “ready for action” component state
public void setCodeSender(PhoneVerification.CodeSender codeSender)Sets the server call that sends a code to a number.
public void setCodeVerifier(PhoneVerification.CodeVerifier codeVerifier)Sets the server call that checks a code.
public int getResendDelay()The seconds the user waits before a resend is offered; 60 by default.
public void setResendDelay(int seconds)Sets the seconds before a resend is offered.
public String getPhoneNumber()The number the code was sent to, in E.164 form, or null before a code has been requested.
public PhoneNumberField getPhoneNumberField()The number entry field, exposed for theming and for narrowing the country list.
public OtpField getOtpField()The code entry field, exposed for theming.
public Button getSendButton()The button that sends the first code, exposed for theming and for relabelling.
public Button getVerifyButton()The button that submits a typed code, exposed for theming.
public Button getResendButton()The button that asks for another code, exposed for theming.
public Button getChangeNumberButton()The button that returns to the number stage, exposed for theming.
public void addVerifiedListener(ActionListener l)Adds a listener fired when a code is accepted.
public void removeVerifiedListener(ActionListener l)Removes a previously-registered listener.
public void addFailedListener(ActionListener l)Adds a listener fired when either server call reports a failure.
public void removeFailedListener(ActionListener l)Removes a previously-registered listener.

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, calcPreferredSize, 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, 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

Constructor details

PhoneVerification

public PhoneVerification()
Builds the flow with a six digit code.

PhoneVerification

public PhoneVerification(int codeLength)
Builds the flow with a code of the given length.

Parameters

codeLength int
the number of digits in the code

Method details

showNumberStage

public void showNumberStage()
Returns to the first stage, with the number as it was left, and clears any code that was typed.

showCodeStage

public void showCodeStage(String e164Number)
Moves to the code stage for a number, as though the code had just been sent. Useful when the application sent the message itself rather than through #setCodeSender(CodeSender).

Parameters

e164Number String
the number the code went to

isCodeStage

public boolean isCodeStage()
True when the code stage is showing.

requestCode

public void requestCode(String e164Number)
Sends a code to a number, moving to the code stage when the server accepts it. Called by the send and resend buttons; an application driving the flow from its own button calls it directly.

Parameters

e164Number String
the number to send to

isPlausibleE164

public static boolean isPlausibleE164(String e164Number)
The shape a number must have before a request is worth making: a “+”, then between five and fifteen digits, which is what E.164 allows. It is not a check that the number exists – that is the sending service’s answer, and its refusal is shown to the user like any other failure.

Parameters

e164Number String
the number to check

Returns

true when the number is worth sending to

submitCode

public void submitCode()
Verifies the code currently entered. Called when the last box is filled and by the verify button.

deinitialize

protected void deinitialize()
Invoked to indicate that the component initialization is being reversed since the component was detached from the container hierarchy. This allows the component to deregister animators and cleanup after itself. This method is the opposite of the initComponent() method.

initComponent

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

setCodeSender

public void setCodeSender(PhoneVerification.CodeSender codeSender)
Sets the server call that sends a code to a number.

Parameters

codeSender PhoneVerification.CodeSender
the sender

setCodeVerifier

public void setCodeVerifier(PhoneVerification.CodeVerifier codeVerifier)
Sets the server call that checks a code.

Parameters

codeVerifier PhoneVerification.CodeVerifier
the verifier

getResendDelay

public int getResendDelay()
The seconds the user waits before a resend is offered; 60 by default.

setResendDelay

public void setResendDelay(int seconds)
Sets the seconds before a resend is offered. Zero offers it at once.

Parameters

seconds int
the delay

getPhoneNumber

public String getPhoneNumber()
The number the code was sent to, in E.164 form, or null before a code has been requested.

getPhoneNumberField

public PhoneNumberField getPhoneNumberField()
The number entry field, exposed for theming and for narrowing the country list.

getOtpField

public OtpField getOtpField()
The code entry field, exposed for theming.

getSendButton

public Button getSendButton()
The button that sends the first code, exposed for theming and for relabelling.

getVerifyButton

public Button getVerifyButton()
The button that submits a typed code, exposed for theming. The code is also submitted as soon as the last box is filled.

getResendButton

public Button getResendButton()
The button that asks for another code, exposed for theming.

getChangeNumberButton

public Button getChangeNumberButton()
The button that returns to the number stage, exposed for theming.

addVerifiedListener

public void addVerifiedListener(ActionListener l)
Adds a listener fired when a code is accepted.

Parameters

l ActionListener
the listener

removeVerifiedListener

public void removeVerifiedListener(ActionListener l)
Removes a previously-registered listener.

Parameters

l ActionListener
the listener

addFailedListener

public void addFailedListener(ActionListener l)
Adds a listener fired when either server call reports a failure. The failure is already shown to the user; this is for an application that wants to count attempts or log them.

Parameters

l ActionListener
the listener

removeFailedListener

public void removeFailedListener(ActionListener l)
Removes a previously-registered listener.

Parameters

l ActionListener
the listener