5

In the assets folder of my Android App Project I am storing custom XML files which describe actions in my game. Since they are a little more complex, they can not be directly written as Android Resources.

Update: I am storing my custom (complex) XML files in the res/xml folder now.

Simple Example:

<dialog>
    <npc>1</npc>
    <text>Hello! How are you?</text>
</dialog>

What I want is to use the convenient advantages of Android String resources for language localisation. In the example above, I want to save Hello! How are you? in my res/values/strings.xml and then reference this somehow like this:

<text>@string/dialog_1_text</text>

I do not want to create different language res/xml folders where I copy all xml files and translate them completely. I only want parts of it to be translated. Easily by referencing a String resource.

Update 2: I have now found out that the XMLParser that you get from Resource.getXml() has a method called getAttributeResourceValue() which converts an attribute like randomAtt="@string/random_string" automatically to an actual Resource ID.
However, in the XML file, there still is no clear dependency and there is no preview for the string or a warning when you put in an invalid resource. But - since there even is a method for that - I strongly believe that it is possible to let the validator only allow string resources in some custom attributes.

5
  • Why do you want to store it as an asset if it has localizable strings? It will be better to store them in xml directory under resources rather than assets. Commented Feb 26, 2016 at 19:17
  • 2
    Because all XML files in the Resource folder need to follow a certain Android structure. And for some tasks I need more complex XML files with my own schemas. That's not allowed in res. Commented Feb 26, 2016 at 20:09
  • 1
    As per Android documentation, you can create a directory "xml" under resources and store arbitrary xml there. Have you explored that option? Did you run into any limitations in using this approach? Commented Feb 26, 2016 at 20:21
  • 1
    Ah, wow, how did I not notice that! Thank you! ... Though, the question remains: How do I now reference a string from inside that? I tried typing @string/ in a custom text-tag but there was no auto-complete, so I assume it's not referenceable. Commented Feb 26, 2016 at 20:30
  • I updated the first post, thanks to @greenrobo. Though, I still have no clue how to reference string resources in custom xml resource files now. Commented Feb 26, 2016 at 21:10

1 Answer 1

10

Okay, so after a lot of research in the past two hours, I finally found a very well working solution. I have seen a few threads which ask very similar questions - that's why I am sure this answer might help some programmers in the future.

Requirements:
The requirements for my task were the following: Referencing String Resources in a custom XML file with my own schema, stored in the res/xml directory. The XML Validator of Android Studio should automatically detect it as a String resource, print a warning when it is invalid - and preview the actual String when it is a valid resource. Also it should be as performant as possible.

Solution:
And this is how I solved it:
Instead of putting the string resource between the tags, I had to put them as an attribute. No big deal in my case.
And for the validator to recognize them as String resource, I had to call these attributes text from the android namespace: Update: I found out that you can call the attribute whatever you like, and it is not necessary to include the android namespace.

<main>
    <nested>
        <test myText="@string/lorem_ipsum_100"/>
    </nested>
</main>

(Your custom XML may look as whatever you like/need! This is just an example - it works with unlimited nested tags and your own defined schema.)

I didn't think this was gonna work - but it actually does quite well! Whenever I hit Build project, it prints out a warning when I used an invalid String resource.
And not only that, it also previews it as desired: String preview in Android Studio

(Note: This screenshot was made before I noticed that you can call the attribute whatever you want/need. There is no need to call it explicitely android:text. Android Studio will automatically recognize it as a string resource, as long as you put @string/....)

Now last but not least, to let your Java code interpret the resource correctly, you have to do this:

XmlResourceParser parser = getResources().getXml(R.xml.tutorial_welcome_dialog);
try {
    while (parser.next() != XmlPullParser.END_DOCUMENT) {
        if (parser.getEventType() == XmlPullParser.START_TAG && parser.getName().equals("test")) {
            String s;
            for (int i = 0; i < parser.getAttributeCount(); i++) {
                if (parser.getAttributeName(i).equals("text"))
                    s = getResources().getString(parser.getAttributeResourceValue(i, -1));
            }
        }

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

Performance note: As far as I can see, this solution is also super performant, since android pre-parses the @string/... automatically into Resource IDs.

Sign up to request clarification or add additional context in comments.

1 Comment

Is there any way to make android also pre-parse the reference when not in an attribute value, but when between two XML tags?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.