diff --git a/shell/platform/android/io/flutter/embedding/engine/systemchannels/SpellCheckChannel.java b/shell/platform/android/io/flutter/embedding/engine/systemchannels/SpellCheckChannel.java index ca17b264e4853..ecbfaead02cf2 100644 --- a/shell/platform/android/io/flutter/embedding/engine/systemchannels/SpellCheckChannel.java +++ b/shell/platform/android/io/flutter/embedding/engine/systemchannels/SpellCheckChannel.java @@ -8,11 +8,10 @@ import androidx.annotation.Nullable; import io.flutter.Log; import io.flutter.embedding.engine.dart.DartExecutor; -import io.flutter.plugin.common.JSONMethodCodec; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; -import org.json.JSONArray; -import org.json.JSONException; +import io.flutter.plugin.common.StandardMethodCodec; +import java.util.ArrayList; /** * {@link SpellCheckChannel} is a platform channel that is used by the framework to initiate spell @@ -26,9 +25,8 @@ * *

Once the spell check results are received by the {@link * io.flutter.plugin.editing.SpellCheckPlugin}, it will send back to the framework the {@code - * ArrayList} of encoded spell check results (see {@link - * io.flutter.plugin.editing.SpellCheckPlugin#onGetSentenceSuggestions} for details). For example, - * the argument may look like: {@code {"7.11.world\nword\nold"}}. The {@link + * ArrayList>} of spell check results (see {@link + * io.flutter.plugin.editing.SpellCheckPlugin#onGetSentenceSuggestions} for details). The {@link * io.flutter.plugin.editing.SpellCheckPlugin} only handles one request to fetch spell check results * at a time; see {@link io.flutter.plugin.editing.SpellCheckPlugin#initiateSpellCheck} for details. * @@ -59,11 +57,11 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result switch (method) { case "SpellCheck.initiateSpellCheck": try { - final JSONArray argumentList = (JSONArray) args; - String locale = argumentList.getString(0); - String text = argumentList.getString(1); + final ArrayList argumentList = (ArrayList) args; + String locale = argumentList.get(0); + String text = argumentList.get(1); spellCheckMethodHandler.initiateSpellCheck(locale, text, result); - } catch (JSONException exception) { + } catch (IllegalStateException exception) { result.error("error", exception.getMessage(), null); } break; @@ -75,7 +73,7 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result }; public SpellCheckChannel(@NonNull DartExecutor dartExecutor) { - channel = new MethodChannel(dartExecutor, "flutter/spellcheck", JSONMethodCodec.INSTANCE); + channel = new MethodChannel(dartExecutor, "flutter/spellcheck", StandardMethodCodec.INSTANCE); channel.setMethodCallHandler(parsingMethodHandler); } diff --git a/shell/platform/android/io/flutter/plugin/editing/SpellCheckPlugin.java b/shell/platform/android/io/flutter/plugin/editing/SpellCheckPlugin.java index 3f9d00951d347..1bfc503a73c4c 100644 --- a/shell/platform/android/io/flutter/plugin/editing/SpellCheckPlugin.java +++ b/shell/platform/android/io/flutter/plugin/editing/SpellCheckPlugin.java @@ -15,6 +15,7 @@ import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.localization.LocalizationPlugin; import java.util.ArrayList; +import java.util.HashMap; import java.util.Locale; /** @@ -34,6 +35,10 @@ public class SpellCheckPlugin private final TextServicesManager mTextServicesManager; private SpellCheckerSession mSpellCheckerSession; + public static final String START_INDEX_KEY = "startIndex"; + public static final String END_INDEX_KEY = "endIndex"; + public static final String SUGGESTIONS_KEY = "suggestions"; + @VisibleForTesting MethodChannel.Result pendingResult; // The maximum number of suggestions that the Android spell check service is allowed to provide @@ -105,19 +110,28 @@ public void performSpellCheck(@NonNull String locale, @NonNull String text) { * Callback for Android spell check API that decomposes results and send results through the * {@link SpellCheckChannel}. * - *

Spell check results will be encoded as a string representing the span of that result, with - * the format "start_index.end_index.suggestion_1/nsuggestion_2/nsuggestion_3", where there may be - * up to 5 suggestions. + *

Spell check results are encoded as dictionaries with a format that looks like + * + *

{@code
+   * {
+   *   startIndex: 0,
+   *   endIndex: 5,
+   *   suggestions: [hello, ...]
+   * }
+   * }
+ * + * where there may be up to 5 suggestions. */ @Override public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results) { if (results.length == 0) { - pendingResult.success(new ArrayList()); + pendingResult.success(new ArrayList>()); pendingResult = null; return; } - ArrayList spellCheckerSuggestionSpans = new ArrayList(); + ArrayList> spellCheckerSuggestionSpans = + new ArrayList>(); SentenceSuggestionsInfo spellCheckResults = results[0]; for (int i = 0; i < spellCheckResults.getSuggestionsCount(); i++) { @@ -128,19 +142,20 @@ public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results) { continue; } - String spellCheckerSuggestionSpan = ""; + HashMap spellCheckerSuggestionSpan = new HashMap(); int start = spellCheckResults.getOffsetAt(i); - int end = start + spellCheckResults.getLengthAt(i) - 1; + int end = start + spellCheckResults.getLengthAt(i); - spellCheckerSuggestionSpan += String.valueOf(start) + "."; - spellCheckerSuggestionSpan += String.valueOf(end) + "."; + spellCheckerSuggestionSpan.put(START_INDEX_KEY, start); + spellCheckerSuggestionSpan.put(END_INDEX_KEY, end); + ArrayList suggestions = new ArrayList(); for (int j = 0; j < suggestionsCount; j++) { - spellCheckerSuggestionSpan += suggestionsInfo.getSuggestionAt(j) + "\n"; + suggestions.add(suggestionsInfo.getSuggestionAt(j)); } - spellCheckerSuggestionSpans.add( - spellCheckerSuggestionSpan.substring(0, spellCheckerSuggestionSpan.length() - 1)); + spellCheckerSuggestionSpan.put(SUGGESTIONS_KEY, suggestions); + spellCheckerSuggestionSpans.add(spellCheckerSuggestionSpan); } pendingResult.success(spellCheckerSuggestionSpans); diff --git a/shell/platform/android/test/io/flutter/plugin/editing/SpellCheckPluginTest.java b/shell/platform/android/test/io/flutter/plugin/editing/SpellCheckPluginTest.java index aa450c6dfe518..559ebcbae2a7a 100644 --- a/shell/platform/android/test/io/flutter/plugin/editing/SpellCheckPluginTest.java +++ b/shell/platform/android/test/io/flutter/plugin/editing/SpellCheckPluginTest.java @@ -21,12 +21,13 @@ import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.embedding.engine.systemchannels.SpellCheckChannel; import io.flutter.plugin.common.BinaryMessenger; -import io.flutter.plugin.common.JSONMethodCodec; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.StandardMethodCodec; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.Locale; import org.junit.Test; import org.junit.runner.RunWith; @@ -38,7 +39,7 @@ public class SpellCheckPluginTest { private static void sendToBinaryMessageHandler( BinaryMessenger.BinaryMessageHandler binaryMessageHandler, String method, Object args) { MethodCall methodCall = new MethodCall(method, args); - ByteBuffer encodedMethodCall = JSONMethodCodec.INSTANCE.encodeMethodCall(methodCall); + ByteBuffer encodedMethodCall = StandardMethodCodec.INSTANCE.encodeMethodCall(methodCall); binaryMessageHandler.onMessage( (ByteBuffer) encodedMethodCall.flip(), mock(BinaryMessenger.BinaryReply.class)); } @@ -185,7 +186,7 @@ public void onGetSentenceSuggestionsResultsWithSuccessAndNoResultsProperly() { spellCheckPlugin.onGetSentenceSuggestions(new SentenceSuggestionsInfo[] {}); - verify(mockResult).success(new ArrayList()); + verify(mockResult).success(new ArrayList>()); } @Test @@ -209,6 +210,16 @@ public void onGetSentenceSuggestionsResultsWithSuccessAndResultsProperly() { new int[] {5}) }); - verify(mockResult).success(new ArrayList(Arrays.asList("7.11.world\nword\nold"))); + ArrayList> expectedResults = new ArrayList>(); + HashMap expectedResult = new HashMap(); + + expectedResult.put(SpellCheckPlugin.START_INDEX_KEY, 7); + expectedResult.put(SpellCheckPlugin.END_INDEX_KEY, 12); + expectedResult.put( + SpellCheckPlugin.SUGGESTIONS_KEY, + new ArrayList(Arrays.asList("world", "word", "old"))); + expectedResults.add(expectedResult); + + verify(mockResult).success(expectedResults); } }