Odd behavior: Class type of the object retuned by the getText() method of TextView changes after creating AccessibilityNodeInfo of TextView

android, android-layout, textview

Solution

It is due to new features like `select`, `cut`, `copy`, `paste` features added to the `AccessibilityNodeInfo`. It was introduced in Android 4.3 and is documented here.

Select text and copy/paste

The AccessibilityNodeInfo now provides APIs that allow an AccessibilityService to select, cut, copy, and paste text in a node.

To specify the selection of text to cut or copy, your accessibility service can use the new action, ACTION_SET_SELECTION, passing with it the selection start and end position with ACTION_ARGUMENT_SELECTION_START_INT and ACTION_ARGUMENT_SELECTION_END_INT. Alternatively you can select text by manipulating the cursor position using the existing action, ACTION_NEXT_AT_MOVEMENT_GRANULARITY (previously only for moving the cursor position), and adding the argument ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN.

You can then cut or copy with ACTION_CUT, ACTION_COPY, then later paste with ACTION_PASTE.

Note: These new APIs are also available for previous versions of Android through the Android Support Library, with the AccessibilityNodeInfoCompat class.

To implement the `select` feature, the `styleable` / `markup` objects need to be attached to the underlying text. Hence the text type is changed from `String` to `SpannableString`.

Here is the code of View.java which introduced this feature. Following code changes the type to `SpannableString`.

@Override
public CharSequence getIterableTextForAccessibility() {
    if (!(mText instanceof Spannable)) {
        setText(mText, BufferType.SPANNABLE);
    }
    return mText;
}

Problem

I have a TextView with text "Hello World!" defined in layout xml ``` TextView textView = (TextView)findViewById(R.id.textView); ``` TextView's getText() method returns object of Class java.lang.String ``` //Returns object of String class Toast.makeText(getApplicationContext(), textView.getText().getClass().getName(), Toast.LENGTH_LONG).show(); ``` If the same is called after creating AccessibilityNodeInfo, it returns object of android.text.SpannableString ``` //Creating AccessibilityNodeInfo AccessibilityNodeInfo info = textView.createAccessibilityNodeInfo(); //Returns object of SpannableString Toast.makeText(getApplicationContext(), "After creating AccessibilityNodeInfo: " + textView.getText().getClass().getName(), Toast.LENGTH_LONG).show(); ``` How is creating AccessibilityNodeInfo relevant to the object returned by the getText() method? Note: This only happens in Android 4.3 and above

Original source