Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Oct 22, 2025

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description

Fixes a crash on Android when modifying Entry.Text within a TextChanged event handler. The crash occurred with the error:

java.lang.IllegalArgumentException: end should be < than charSequence length
at androidx.emoji2.text.EmojiCompat.process(EmojiCompat.java:1127)
at androidx.emoji2.viewsintegration.EmojiTextWatcher.afterTextChanged(EmojiTextWatcher.java:99)

Root Cause

The issue was a race condition in EditTextExtensions.UpdateText() where SetSelection() could be called with a position exceeding the actual text length. This happened because:

  1. User deletes text in an Entry, making it empty
  2. TextChanged event fires with the empty text
  3. Event handler sets Text = "0" to provide a default value
  4. Meanwhile, Android's EmojiCompat text watcher is still processing the deletion with the old text length
  5. When SetSelection() is called, the text length has changed, causing an out-of-bounds error

Changes

Added defensive bounds checking to all SetSelection() calls in EditTextExtensions.cs:

  • UpdateText(EditText, IEntry) - Entry text updates
  • UpdateText(EditText, IEditor) - Editor text updates
  • SetInputType() - Cursor position restoration after input type changes

The fix uses Math.Min() to ensure the selection position never exceeds the current text length:

int selectionPosition = Math.Min(editText.Text?.Length ?? 0, editText.Length());
editText.SetSelection(selectionPosition);

Testing

Added UI test case that reproduces the original crash scenario:

  • Entry with numeric keyboard and initial text "0"
  • TextChanged handler that sets text to "0" when empty
  • Test clears the Entry and verifies no crash occurs

Issues Fixed

Fixes android crash when setting Entry.Text in TextChanged event handler (related to EmojiCompat bounds checking)

Original prompt

This section details on the original issue you should resolve

<issue_title>end should be < than charSequence length</issue_title>
<issue_description>### Description

I am getting a crash when using TextChanged on a Entry modifying the value.

Steps to Reproduce

  1. Create a new .net Maui App
  2. Add to the MainPage.xaml
            <Entry x:Name="CartonsEntry" Grid.Column="1" HorizontalOptions="Fill" Text="0" Keyboard="Numeric" TextChanged="Quantity_TextChanged" />
  1. Add to the code behind
        private void Quantity_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (string.IsNullOrEmpty(e.NewTextValue))
            {
                ((Entry)sender).Text = "0";
            }
        }
  1. Run app
  2. Delete the contents of the entry box
  3. Fatal error

Link to public reproduction project repository

https://github.com/jdarwood007/MauiApp9

Version with bug

9.0.110 SR11

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 14

Did you find any workaround?

The problem seems to be entirely calling this:

                ((Entry)sender).Text = "0";

Relevant log output

[MessageQueue-JNI] Exception in MessageQueue callback: handleReceiveCallback

[MessageQueue-JNI] java.lang.IllegalArgumentException: end should be < than charSequence length

[MessageQueue-JNI] 	at androidx.core.util.Preconditions.checkArgument(Preconditions.java:52)

[MessageQueue-JNI] 	at androidx.emoji2.text.EmojiCompat.process(EmojiCompat.java:1127)

[MessageQueue-JNI] 	at androidx.emoji2.viewsintegration.EmojiTextWatcher.afterTextChanged(EmojiTextWatcher.java:99)

[MessageQueue-JNI] 	at android.widget.TextView.sendAfterTextChanged(TextView.java:12365)

[MessageQueue-JNI] 	at android.widget.TextView$ChangeWatcher.afterTextChanged(TextView.java:15851)

[MessageQueue-JNI] 	at android.text.SpannableStringBuilder.sendAfterTextChanged(SpannableStringBuilder.java:1278)

[MessageQueue-JNI] 	at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:578)

[MessageQueue-JNI] 	at androidx.emoji2.text.SpannableBuilder.replace(SpannableBuilder.java:308)

[MessageQueue-JNI] 	at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:231)

[MessageQueue-JNI] 	at androidx.emoji2.text.SpannableBuilder.delete(SpannableBuilder.java:330)

[MessageQueue-JNI] 	at androidx.emoji2.text.SpannableBuilder.delete(SpannableBuilder.java:48)

[MessageQueue-JNI] 	at android.text.method.BaseKeyListener.backspaceOrForwardDelete(BaseKeyListener.java:372)

[MessageQueue-JNI] 	at android.text.method.BaseKeyListener.backspace(BaseKeyListener.java:71)

[MessageQueue-JNI] 	at android.text.method.BaseKeyListener.onKeyDown(BaseKeyListener.java:498)

[MessageQueue-JNI] 	at android.text.method.NumberKeyListener.onKeyDown(NumberKeyListener.java:146)

[MessageQueue-JNI] 	at android.widget.TextView.doKeyDown(TextView.java:9511)

[MessageQueue-JNI] 	at android.widget.TextView.onKeyDown(TextView.java:9283)

[MessageQueue-JNI] 	at android.view.KeyEvent.dispatch(KeyEvent.java:2928)

[MessageQueue-JNI] 	at android.view.View.dispatchKeyEvent(View.java:15591)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at androidx.core.widget.NestedScrollView.dispatchKeyEvent(NestedScrollView.java:688)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at androidx.recyclerview.widget.RecyclerView.dispatchKeyEvent(RecyclerView.java:1981)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at androidx.coordinatorlayout.widget.CoordinatorLayout.dispatchKeyEvent(CoordinatorLayout.java:1946)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1966)

[MessageQueue-JNI] 	at android.view.ViewGroup.dispatchKeyEvent(ViewGrou...

</details>

Fixes dotnet/maui#32004

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for you](https://github.com/dotnet/maui/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.

@Copilot Copilot AI changed the title [WIP] Fix crash in Quantity_TextChanged on Entry Fix Android crash when setting Entry.Text in TextChanged event handler Oct 22, 2025
Copilot finished work on behalf of jfversluis October 22, 2025 09:59
@Copilot Copilot AI requested a review from jfversluis October 22, 2025 09:59
@jsuarezruiz
Copy link
Contributor

/azp run

@jsuarezruiz jsuarezruiz added t/bug Something isn't working area-controls-entry Entry labels Oct 22, 2025
@azure-pipelines
Copy link

Azure Pipelines successfully started running 3 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-entry Entry t/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants