Package io.flutter.view

# Class AccessibilityBridge

java.lang.Object
android.view.accessibility.AccessibilityNodeProvider
io.flutter.view.AccessibilityBridge

public class AccessibilityBridge extends AccessibilityNodeProvider
Bridge between Android's OS accessibility system and Flutter's accessibility system.

An `AccessibilityBridge` requires:

- A real Android `View`, called the `rootAccessibilityView`, which contains a Flutter UI. The `rootAccessibilityView` is required at the time of `AccessibilityBridge`'s instantiation and is held for the duration of `AccessibilityBridge`'s lifespan. `AccessibilityBridge` invokes various accessibility methods on the `rootAccessibilityView`, e.g., `View.onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)`. The `rootAccessibilityView` is expected to notify the `AccessibilityBridge` of relevant interactions: `onAccessibilityHoverEvent(MotionEvent)`, `reset()`, `updateSemantics(ByteBuffer, String[], ByteBuffer[])`, and `updateCustomAccessibilityActions(ByteBuffer, String[])`
- An `AccessibilityChannel` that is connected to the running Flutter app.
- Android's `AccessibilityManager` to query and listen for accessibility settings.
- Android's `ContentResolver` to listen for changes to system animation settings.

The `AccessibilityBridge` causes Android to treat Flutter `SemanticsNode`s as if they were accessible Android `View`s. Accessibility requests may be sent from a Flutter widget to the Android OS, as if it were an Android `View`, and accessibility events may be consumed by a Flutter widget, as if it were an Android `View`. `AccessibilityBridge` refers to Flutter's accessible widgets as "virtual views" and identifies them with "virtual view IDs".

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `static enum`
  `AccessibilityBridge.Action`
  `static interface`
  `AccessibilityBridge.OnAccessibilityChangeListener`
  Listener that can be set on a `AccessibilityBridge`, which is invoked any time accessibility is turned on/off, or touch exploration is turned on/off.

- ## Field Summary

  ### Fields inherited from class android.view.accessibility.AccessibilityNodeProvider

  `HOST_VIEW_ID`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `AccessibilityBridge(View rootAccessibilityView, AccessibilityChannel accessibilityChannel, AccessibilityManager accessibilityManager, ContentResolver contentResolver, PlatformViewsAccessibilityDelegate platformViewsAccessibilityDelegate)`
  `AccessibilityBridge(View rootAccessibilityView, AccessibilityChannel accessibilityChannel, AccessibilityManager accessibilityManager, ContentResolver contentResolver, io.flutter.view.AccessibilityViewEmbedder accessibilityViewEmbedder, PlatformViewsAccessibilityDelegate platformViewsAccessibilityDelegate)`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `AccessibilityNodeInfo`
  `createAccessibilityNodeInfo(int virtualViewId)`
  Returns `AccessibilityNodeInfo` for the view corresponding to the given `virtualViewId`.
  `boolean`
  `externalViewRequestSendAccessibilityEvent(View embeddedView, View eventOrigin, AccessibilityEvent event)`
  Delegates handling of `ViewParent.requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent)` to the accessibility bridge.
  `AccessibilityNodeInfo`
  `findFocus(int focus)`
  Finds the view in a hierarchy that currently has the given type of `focus`.
  `boolean`
  `getAccessibleNavigation()`
  `int`
  `getHoveredObjectId()`
  `boolean`
  `isAccessibilityEnabled()`
  Returns true if the Android OS currently has accessibility enabled, false otherwise.
  `boolean`
  `isTouchExplorationEnabled()`
  Returns true if the Android OS currently has touch exploration enabled, false otherwise.
  `AccessibilityEvent`
  `obtainAccessibilityEvent(int eventType)`
  `AccessibilityNodeInfo`
  `obtainAccessibilityNodeInfo(View rootView)`
  `AccessibilityNodeInfo`
  `obtainAccessibilityNodeInfo(View rootView, int virtualViewId)`
  `boolean`
  `onAccessibilityHoverEvent(MotionEvent event)`
  A hover `MotionEvent` has occurred in the `View` that corresponds to this `AccessibilityBridge`.
  `boolean`
  `onAccessibilityHoverEvent(MotionEvent event, boolean ignorePlatformViews)`
  A hover `MotionEvent` has occurred in the `View` that corresponds to this `AccessibilityBridge`.
  `boolean`
  `performAction(int virtualViewId, int accessibilityAction, Bundle arguments)`
  Instructs the view represented by `virtualViewId` to carry out the desired `accessibilityAction`, perhaps configured by additional `arguments`.
  `void`
  `release()`
  Disconnects any listeners and/or delegates that were initialized in `AccessibilityBridge`'s constructor, or added after.
  `void`
  `reset()`
  Resets the `AccessibilityBridge`: Clears `flutterSemanticsTree`, the Android cache of Flutter's semantics tree Releases focus on any active `accessibilityFocusedSemanticsNode` Clears any hovered `SemanticsNode` Sends a `AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED` event
  `void`
  `sendAccessibilityEvent(int viewId, int eventType)`
  Sends an accessibility event of the given `eventType` to Android's accessibility system with the given `viewId` represented as the source of the event.
  `void`
  `setOnAccessibilityChangeListener(AccessibilityBridge.OnAccessibilityChangeListener listener)`
  Sets a listener on this `AccessibilityBridge`, which is notified whenever accessibility activation, or touch exploration activation changes.

  ### Methods inherited from class android.view.accessibility.AccessibilityNodeProvider

  `addExtraDataToAccessibilityNodeInfo, findAccessibilityNodeInfosByText`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Constructor Details

  - ### AccessibilityBridge

    public AccessibilityBridge(@NonNull View rootAccessibilityView, @NonNull AccessibilityChannel accessibilityChannel, @NonNull AccessibilityManager accessibilityManager, @NonNull ContentResolver contentResolver, @NonNull PlatformViewsAccessibilityDelegate platformViewsAccessibilityDelegate)

  - ### AccessibilityBridge

    @VisibleForTesting public AccessibilityBridge(@NonNull View rootAccessibilityView, @NonNull AccessibilityChannel accessibilityChannel, @NonNull AccessibilityManager accessibilityManager, @NonNull ContentResolver contentResolver, @NonNull io.flutter.view.AccessibilityViewEmbedder accessibilityViewEmbedder, @NonNull PlatformViewsAccessibilityDelegate platformViewsAccessibilityDelegate)

- ## Method Details

  - ### getHoveredObjectId

    @VisibleForTesting public int getHoveredObjectId()

  - ### getAccessibleNavigation

    @VisibleForTesting public boolean getAccessibleNavigation()

  - ### release

    public void release()
    Disconnects any listeners and/or delegates that were initialized in `AccessibilityBridge`'s constructor, or added after.

    Do not use this instance after invoking `release`. The behavior of any method invoked on this `AccessibilityBridge` after invoking `release()` is undefined.

  - ### isAccessibilityEnabled

    public boolean isAccessibilityEnabled()
    Returns true if the Android OS currently has accessibility enabled, false otherwise.

  - ### isTouchExplorationEnabled

    public boolean isTouchExplorationEnabled()
    Returns true if the Android OS currently has touch exploration enabled, false otherwise.

  - ### setOnAccessibilityChangeListener

    public void setOnAccessibilityChangeListener(@Nullable AccessibilityBridge.OnAccessibilityChangeListener listener)
    Sets a listener on this `AccessibilityBridge`, which is notified whenever accessibility activation, or touch exploration activation changes.

  - ### obtainAccessibilityNodeInfo

    @VisibleForTesting public AccessibilityNodeInfo obtainAccessibilityNodeInfo(View rootView)

  - ### obtainAccessibilityNodeInfo

    @VisibleForTesting public AccessibilityNodeInfo obtainAccessibilityNodeInfo(View rootView, int virtualViewId)

  - ### createAccessibilityNodeInfo

    public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId)
    Returns `AccessibilityNodeInfo` for the view corresponding to the given `virtualViewId`.

    This method is invoked by Android's accessibility system when Android needs accessibility info for a given view.

    When a `virtualViewId` of `View.NO_ID` is requested, accessibility node info is returned for our `rootAccessibilityView`. Otherwise, Flutter's semantics tree, represented by `flutterSemanticsTree`, is searched for a `AccessibilityBridge.SemanticsNode` with the given `virtualViewId`. If no such `AccessibilityBridge.SemanticsNode` is found, then this method returns null. If the desired `AccessibilityBridge.SemanticsNode` is found, then an `AccessibilityNodeInfo` is obtained from the `rootAccessibilityView`, filled with appropriate info, and then returned.

    Depending on the type of Flutter `SemanticsNode` that is requested, the returned `AccessibilityNodeInfo` pretends that the `SemanticsNode` in question comes from a specialize Android view, e.g., `AccessibilityBridge.Flag.IS_TEXT_FIELD` maps to `android.widget.EditText`, `AccessibilityBridge.Flag.IS_BUTTON` maps to `android.widget.Button`, and `AccessibilityBridge.Flag.IS_IMAGE` maps to `android.widget.ImageView`. In the case that no specialized view applies, the returned `AccessibilityNodeInfo` pretends that it represents a `android.view.View`.

    Overrides:
      `createAccessibilityNodeInfo` in class `AccessibilityNodeProvider`

  - ### performAction

    public boolean performAction(int virtualViewId, int accessibilityAction, @Nullable Bundle arguments)
    Instructs the view represented by `virtualViewId` to carry out the desired `accessibilityAction`, perhaps configured by additional `arguments`.

    This method is invoked by Android's accessibility system. This method returns true if the desired `SemanticsNode` was found and was capable of performing the desired action, false otherwise.

    In a traditional Android app, the given view ID refers to a `View` within an Android `View` hierarchy. Flutter does not have an Android `View` hierarchy, therefore the given view ID is a `virtualViewId` that refers to a `SemanticsNode` within a Flutter app. The given arguments of this method are forwarded from Android to Flutter.

    Overrides:
      `performAction` in class `AccessibilityNodeProvider`

  - ### findFocus

    public AccessibilityNodeInfo findFocus(int focus)
    Finds the view in a hierarchy that currently has the given type of `focus`.

    This method is invoked by Android's accessibility system.

    Flutter does not have an Android `View` hierarchy. Therefore, Flutter conceptually handles this request by searching its semantics tree for the given `focus`, represented by `flutterSemanticsTree`. In practice, this `AccessibilityBridge` always caches any active `accessibilityFocusedSemanticsNode` and `inputFocusedSemanticsNode`. Therefore, no searching is necessary. This method directly inspects the given `focus` type to return one of the cached nodes, null if the cached node is null, or null if a different `focus` type is requested.

    Overrides:
      `findFocus` in class `AccessibilityNodeProvider`

  - ### onAccessibilityHoverEvent

    public boolean onAccessibilityHoverEvent(MotionEvent event)
    A hover `MotionEvent` has occurred in the `View` that corresponds to this `AccessibilityBridge`.

    This method returns true if Flutter's accessibility system handled the hover event, false otherwise.

    This method should be invoked from the corresponding `View`'s `View.onHoverEvent(MotionEvent)`.

  - ### onAccessibilityHoverEvent

    public boolean onAccessibilityHoverEvent(MotionEvent event, boolean ignorePlatformViews)
    A hover `MotionEvent` has occurred in the `View` that corresponds to this `AccessibilityBridge`.

    If `ignorePlatformViews` is true, if hit testing for the event finds a platform view, the event will not be handled. This is useful when handling accessibility events for views overlaying platform views. See `PlatformOverlayView` for details.

    This method returns true if Flutter's accessibility system handled the hover event, false otherwise.

    This method should be invoked from the corresponding `View`'s `View.onHoverEvent(MotionEvent)`.

  - ### sendAccessibilityEvent

    @VisibleForTesting public void sendAccessibilityEvent(int viewId, int eventType)
    Sends an accessibility event of the given `eventType` to Android's accessibility system with the given `viewId` represented as the source of the event.

    The given `viewId` may either belong to `rootAccessibilityView`, or any Flutter `AccessibilityBridge.SemanticsNode`.

  - ### obtainAccessibilityEvent

    @VisibleForTesting public AccessibilityEvent obtainAccessibilityEvent(int eventType)

  - ### reset

    public void reset()
    Resets the `AccessibilityBridge`:
    - Clears `flutterSemanticsTree`, the Android cache of Flutter's semantics tree
    - Releases focus on any active `accessibilityFocusedSemanticsNode`
    - Clears any hovered `SemanticsNode`
    - Sends a `AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED` event

  - ### externalViewRequestSendAccessibilityEvent

    public boolean externalViewRequestSendAccessibilityEvent(View embeddedView, View eventOrigin, AccessibilityEvent event)
    Delegates handling of `ViewParent.requestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent)` to the accessibility bridge.

    This is used by embedded platform views to propagate accessibility events from their view hierarchy to the accessibility bridge.

    As the embedded view doesn't have to be the only View in the embedded hierarchy (it can have child views) and the event might have been originated from any view in this hierarchy, this method gets both a reference to the embedded platform view, and a reference to the view from its hierarchy that sent the event.

    Parameters:
      `embeddedView` - the embedded platform view for which the event is delegated
      `eventOrigin` - the view in the embedded view's hierarchy that sent the event.
    Returns:
      True if the event was sent.