diff --git a/engine/src/flutter/shell/platform/android/io/flutter/Build.java b/engine/src/flutter/shell/platform/android/io/flutter/Build.java index 09662c6dad..519cbeff55 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/Build.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/Build.java @@ -11,20 +11,37 @@ public class Build { /** For use in place of the Android Build.VERSION_CODES class. */ public static class API_LEVELS { @VisibleForTesting public static final int FLUTTER_MIN = 21; + /** Android 5.0 (Lollipop) */ public static final int API_21 = 21; + /** Android 5.1 (Lollipop MR1) */ public static final int API_22 = 22; + /** Android 6.0 (Marshmallow) */ public static final int API_23 = 23; + /** Android 7.0 (Nougat) */ public static final int API_24 = 24; + /** Android 7.1 (Nougat MR1) */ public static final int API_25 = 25; + /** Android 8.0 (Oreo) */ public static final int API_26 = 26; + /** Android 8.1 (Oreo MR1) */ public static final int API_27 = 27; + /** Android 9 (Pie) */ public static final int API_28 = 28; + /** Android 10 (Q) */ public static final int API_29 = 29; + /** Android 11 (R) */ public static final int API_30 = 30; + /** Android 12 (S) */ public static final int API_31 = 31; + /** Android 12L (Sv2) */ public static final int API_32 = 32; + /** Android 13 (Tiramisu) */ public static final int API_33 = 33; + /** Android 14 (Upside Down Cake) */ public static final int API_34 = 34; + /** Android 15 (Vanilla Ice Cream) */ public static final int API_35 = 35; + /** Android 16 */ + public static final int API_36 = 36; } } diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java index f2d12b181a..910997a29e 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java @@ -24,6 +24,7 @@ public class AccessibilityChannel { @NonNull public final FlutterJNI flutterJNI; @Nullable private AccessibilityMessageHandler handler; + @SuppressWarnings("deprecation") public final BasicMessageChannel.MessageHandler parsingMessageHandler = new BasicMessageChannel.MessageHandler() { @Override @@ -181,7 +182,16 @@ public class AccessibilityChannel { * {@link AccessibilityChannel#setAccessibilityMessageHandler(AccessibilityMessageHandler)}. */ public interface AccessibilityMessageHandler extends FlutterJNI.AccessibilityDelegate { - /** The Dart application would like the given {@code message} to be announced. */ + /** + * The Dart application would like the given {@code message} to be announced. + * + *

Using AnnounceSemanticsEvent for accessibility is deprecated on Android. Migrate to using + * semantic properties for a more robust and accessible user experience. + * + * @see announceForAccessibility" + */ + @Deprecated(since = "Android API level 36") void announce(@NonNull String message); /** The user has tapped on the semantics node with the given {@code nodeId}. */ diff --git a/engine/src/flutter/shell/platform/android/io/flutter/view/AccessibilityBridge.java b/engine/src/flutter/shell/platform/android/io/flutter/view/AccessibilityBridge.java index 268e9a4e1d..a6cc440ed5 100644 --- a/engine/src/flutter/shell/platform/android/io/flutter/view/AccessibilityBridge.java +++ b/engine/src/flutter/shell/platform/android/io/flutter/view/AccessibilityBridge.java @@ -303,6 +303,13 @@ public class AccessibilityBridge extends AccessibilityNodeProvider { /** The Dart application would like the given {@code message} to be announced. */ @Override public void announce(@NonNull String message) { + if (Build.VERSION.SDK_INT >= API_LEVELS.API_36) { + Log.w( + TAG, + "Using AnnounceSemanticsEvent for accessibility is deprecated on Android. " + + "Migrate to using semantic properties for a more robust and accessible " + + "user experience. See https://developer.android.com/reference/android/view/View#announceForAccessibility(java.lang.CharSequence)"); + } rootAccessibilityView.announceForAccessibility(message); } diff --git a/packages/flutter/lib/src/semantics/semantics_event.dart b/packages/flutter/lib/src/semantics/semantics_event.dart index ac63dd3187..9b9e034d04 100644 --- a/packages/flutter/lib/src/semantics/semantics_event.dart +++ b/packages/flutter/lib/src/semantics/semantics_event.dart @@ -83,6 +83,15 @@ abstract class SemanticsEvent { /// /// When possible, prefer using mechanisms like [Semantics] to implicitly /// trigger announcements over using this event. +/// +/// ### Android +/// Android has [deprecated announcement events][1] due to its disruptive +/// behavior with TalkBack forcing it to clear its speech queue and speak the +/// provided text. Instead, use mechanisms like [Semantics] to implicitly +/// trigger announcements. +/// +/// [1]: https://developer.android.com/reference/android/view/View#announceForAccessibility(java.lang.CharSequence) +/// class AnnounceSemanticsEvent extends SemanticsEvent { /// Constructs an event that triggers an announcement by the platform. const AnnounceSemanticsEvent( diff --git a/packages/flutter/lib/src/semantics/semantics_service.dart b/packages/flutter/lib/src/semantics/semantics_service.dart index 92dff9bfd7..b78864f0d5 100644 --- a/packages/flutter/lib/src/semantics/semantics_service.dart +++ b/packages/flutter/lib/src/semantics/semantics_service.dart @@ -32,6 +32,15 @@ abstract final class SemanticsService { /// The assertiveness level of the announcement is determined by [assertiveness]. /// Currently, this is only supported by the web engine and has no effect on /// other platforms. The default mode is [Assertiveness.polite]. + /// + /// ### Android + /// Android has [deprecated announcement events][1] due to its disruptive + /// behavior with TalkBack forcing it to clear its speech queue and speak the + /// provided text. Instead, use mechanisms like [Semantics] to implicitly + /// trigger announcements. + /// + /// [1]: https://developer.android.com/reference/android/view/View#announceForAccessibility(java.lang.CharSequence) + /// static Future announce( String message, TextDirection textDirection, {