Unicode characters not displayed in TextView.setText

I can't get a TextView to correctly dynamically display unicode characters, and it's driving me batty. I've stripped it down to the bare minimum, but the TextView populated by setText still shows diamonds with question marks inside them for the unicode characters. The version populated from strings.xml shows the multibyte characters perfectly. Here's the activity:

public class TestMultibyteActivity extends Activity
{
  /** Called when the activity is first created. */
  @Override
  public void onCreate( Bundle savedInstanceState )
  {
    super.onCreate( savedInstanceState );
    setContentView( R.layout.main );
    TextView textField = (TextView) findViewById( R.id.text_field );
    String str = "Tübingen systemportefølje";
    Log.d( "MULTIBYTE", str ); //note that this prints the multibyte chars correctly.
    //EDIT: oh crap, no it doesn't.  might be onto something here...
    textField.setText( str );
  }
}

And here's the layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">
  <TextView android:id="@+id/text_field"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
  <TextView android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/unicodechars"/>
</LinearLayout>

Here's strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="app_name">TestMultibyteActivity</string>
  <string name="unicodechars">Tübingen systemportefølje</string>
</resources>

I'm building with ant. Here's my default.properties:

target=Google Inc.:Google APIs:8

And here's my AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.mycompany.android.multibyte"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:label="@string/app_name" android:icon="@drawable/icon">
        <activity android:name="TestMultibyteActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest> 

I've tinkered with everything I can think of, but it seems like unicode characters are getting split by the CharSequence interface, and I can't figure out why.


Unfortunately, you just can't do it that way from strings.xml AFAIK.

You're left doing one of two things.

  • Adding the Unicode character within java to the String in the XML file:

    String str = "\u00A9" + getContext().getString(R.string.your_string);
    
  • Entering the text as HTML in java:

    yourTextView.setText(Html.fromHtml("your chars"));
    

Hope this is useful.


The accepted answer is correct but Html.fromHtml is deprecated now. So you'll need to use:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
        textView.setText(Html.fromHtml(user.getInput(), Html.FROM_HTML_MODE_LEGACY));
    } else {
        textView.setText(Html.fromHtml(user.getInput()));
    }

It could be done in such a simple way:

str.replace("uoo26","&");

I had problems trying to display Unicode character from a custom font that were mapped in the Unicode private area. This is a common area where fonts like MaterialDesign and FontAwesome map their icon font characters. Just for clarity I was testing this on an android version 4.4.2 so maybe this is not an issue on later versions (but probably is). I had tried all combinations of "\uF151", &#xF151, and I also tried the Html.fromHtlm. None of these techniques worked to properly display the characters in the Unicode private area. If I keep myself to the range \u00xx, they all worked fine for the fonts that had Unicode codes in those locations. (The two fonts I've mentioned don't have any symbols mapped to those point locations)

In examining the font using Microsoft's Character Map I noticed that the characters in the Unicode private area space where not showing up when I had the Windows-English character set chosen for the fonts. The characters would show up if I selected the Unicode character set; and in the case of the Material Design font if I selected the Japanese character set.

What I did to get the character to display on the in TextView was to change the Locale to Japanese, call setText on the Textview object passing it the correct private area unicode value and the character then displayed correctly. So here's the code I used to set icon font symbol and then revert back to English:

    TextView tv = (TextView)findViewById(R.id.myTextViewObject);
    Typeface tf =  Typeface.createFromAsset(this.getAssets(), "material_design.ttf");
    tv.setTypeface(tf);
    String x = "\uE693";

    tv.setText(x);
    setDefaultLocale(getApplicationContext(),"en");
    tv.append("hello");

And here's the code for the setDefaultLocale method:

public static void setDefaultLocale(Context context, String locale) {
    Locale locJa = new Locale(locale.trim());
    Locale.setDefault(locJa);

    Configuration config = new Configuration();
    config.locale = locJa;

    context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());

    locJa = null;
    config = null;
}

In the case of FontAwesome, you have to select the Tradition Chinese character set to get access to the unicode private area code points.

You might ask, why I didn't select the "Unicode" character set? The character set that android uses is based on the current locale and I couldn't find a way to select unicode as the current locale. In addition, I couldn't find a way to map the private area unicodes into my existing Locale. I also can't tell you whether this is a issue on how these True Type Fonts where constructed or whether this is an Android issue (albeit I think there should have been a why to map the private area code for use in your existing locale) What I have learned is that all Unicode code points are mapped into all language locales for the same font. That's the thing that I think confuses a lot of people about fonts that support unicode. The windows character map was a useful tool for me in determining which character points are mapped into which character set.


Welcome to the world of kotlin,

If someone wants to set a UNICODE programmatically, you can do it the following way

Unicode character for 🤚is U+1F91A

Replace U+ with 0x which makes it 0x1F91A

val unicodeChar = 0x1F91A.toChar() // unicode for 🤚

For the above question user wants to display "Tübingen systemportefølje"

val char1 = 0x00FC.toChar()  // unicode for ü is U+00FC
val char2 = 0x00F8.toChar() //  unicode for ø is U+00F8

val name = StringBuilder("T")
            .append(char1)
            .append("bingen systemportef")
            .append(char2)
            .append("lje")
            .toString()

// OUTPUT name = "Tübingen systemportefølje"

Now you can set the string to your Textview.

For dynamic string, you can search for pattern beginning with 0x and replace it by constructing an equivalent Unicode image.