HTML in string resource?

Android

Android Problem Overview


I know I can put escaped HTML tags in string resources. However, looking at the source code for the Contacts application I can see that they have a way of not having to encode the HTML. Quote from the Contacts application strings.xml:

<string name="contactsSyncPlug"><font fgcolor="#ffffffff">Sync your Google contacts!</font> 
\nAfter syncing to your phone, your contacts will be available to you wherever you go.</string>

Unfortunately, when I try something similar (like Hello, <b>World</b>!), getString() returns the string without the tags (I can see that in logcat). Why is that? How can I get the original string, with tags and everything? How is the Contacts application doing it?

Android Solutions


Solution 1 - Android

You can also surround your html in a CDATA block as well and getString() will return your actual HTML. Like such:

<string name="foo"><![CDATA[Foo Bar <a href="foo?id=%s">baz</a> is cool]]></string>

Now when you perform a getString(R.string.foo) the string will be HTML. If you need to render the HTML (with the link as shown) via a clickable TextView you'd need to perform a Html.fromHtml(...) call to get the spannable text.

Solution 2 - Android

It seems getString() does just that -- gets a string. To use this, you have to use getText() (and no more Html.fromHtml()), i.e.:

mTextView.setText(getText(R.string.my_styled_text));

However, it seems the android:text property does just the same thing, and the following is equivalent:

<TextView android:text="@string/my_styled_text" />

And in strings.xml:

<string name="my_styled_text">Hello, <b>World</b>!</string>

Solution 3 - Android

The best solution is to use resources in a way:

<string name="htmlsource"><![CDATA[<p>Adults are spotted gold and black on the crown, back and wings. Their face and neck are black with a white border; they have a black breast and a dark rump. The legs are black.</p><p>It is similar to two other golden plovers, Eurasian and Pacific. <h1>The American Golden Plover</h1> is smaller, slimmer and relatively longer-legged than Eurasian Golden Plover (<i>Pluvialis apricaria</i>) which also has white axillary (armpit) feathers. It is more similar to Pacific Golden Plover (<i>Pluvialis fulva</i>) with which it was once <b>considered</b> conspecific under the name \"Lesser Golden Plover\". The Pacific Golden Plover is slimmer than the American species, has a shorter primary projection, and longer legs, and is usually yellower on the back.</p><p>These birds forage for food on tundra, fields, beaches and tidal flats, usually by sight. They eat insects and crustaceans, also berries.</p>]]></string>

and than display it with:

Spanned sp = Html.fromHtml( getString(R.string.htmlsource));
tv.setText(sp);

Try to use that resource without <![CDATA[ ]]> and with tv.setText(getText(R.string.htmlsource)); and you will see the difference.

Solution 4 - Android

I know this is an old question but it seems the most efficient answer has not been proposed yet.

Just use HTML-escaped characters so it won't get processed by getString but it will be processed by HtmlCompact.fromHtml (or the older Html.fromHtml).

This also supports more tags like HTML links etc., not only formatting like getString method.

For example something like this should work:

<string name="html_message">Hello &lt;b>World&lt;/b>.</string>

val text = getString(R.string.html_message)
val result = HtmlCompact.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY)

In your case you replace < with &lt; like this:

<string name="contactsSyncPlug">&lt;font fgcolor="#ffffffff">Sync your Google contacts!&lt;/font> \nAfter syncing to your phone, your contacts will be available to you wherever you go.</string>

Solution 5 - Android

it works for me without CDATA block.

<string name="menu_item_purchase" translatable="false"><font color="red">P</font><font color="orange">r</font><font color="yellow">e</font><font color="green">m</font><font color="white">i</font><font color="blue">u</font><font color="purple">m</font></string>`enter code here`

I use it in layout.

<item
    android:id="@+id/nav_premium"
    android:icon="@drawable/coins"
    android:title="@string/menu_item_purchase"
    />

Solution 6 - Android

Idea: put the HTML in JSON-formatted files and store them in /res/raw. (JSON is less picky)

Store the data records like this in an array object:

[
    {
        "Field1": "String data",
        "Field2": 12345,
        "Field3": "more Strings",
        "Field4": true
    },
    {
        "Field1": "String data",
        "Field2": 12345,
        "Field3": "more Strings",
        "Field4": true
    },
    {
        "Field1": "String data",
        "Field2": 12345,
        "Field3": "more Strings",
        "Field4": true
    }
]

To read the data in your app :

private ArrayList<Data> getData(String filename) {
	ArrayList<Data> dataArray = new ArrayList<Data>();
	
	try {
    	int id = getResources().getIdentifier(filename, "raw", getPackageName());
    	InputStream input = getResources().openRawResource(id);
		int size = input.available();
		byte[] buffer = new byte[size];
		input.read(buffer);
		String text = new String(buffer);
		
		Gson gson = new Gson();
		Type dataType = new TypeToken<List<Map<String, Object>>>() {}.getType();
		List<Map<String, Object>> natural = gson.fromJson(text, dataType);

		// now cycle through each object and gather the data from each field
		for(Map<String, Object> json : natural) {
			final Data ad = new Data(json.get("Field1"), json.get("Field2"),  json.get("Field3"), json.get("Field4"));
			dataArray.add(ad);
		}

	} catch (Exception e) {
		e.printStackTrace();
	}
	
	return dataArray;
}

Finally, the Data class is just a container of public variables for easy access...

public class Data {
	
	public String string;
	public Integer number;
	public String somestring;
	public Integer site;
	public boolean logical;

	
	public Data(String string, Integer number, String somestring, boolean logical)
	{
		this.string = string;
		this.number = number;
		this.somestring = somestring;
		this.logical = logical;
	}
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFelixView Question on Stackoverflow
Solution 1 - AndroidDonn FelkerView Answer on Stackoverflow
Solution 2 - AndroidFelixView Answer on Stackoverflow
Solution 3 - Androiduser1006786View Answer on Stackoverflow
Solution 4 - Androidbio007View Answer on Stackoverflow
Solution 5 - AndroidAndrew GlukhoffView Answer on Stackoverflow
Solution 6 - AndroidSomeone SomewhereView Answer on Stackoverflow