5

I created an application that uses the TTS engine to send feedback to the user. With the aim to improve the performance, I used the synthesizeToFile and addSpeech methods, but strings of text to be synthesized are inside the strings.xml file, so I have to invoke these methods for each string that is spoken by the TTS engine.

Since the TTS engine uses only strings whose name begins with tts_, is it possible to easily iterate over all strings that begin with tts_ within the strings.xml file?

enzom83
  • 8,080
  • 10
  • 68
  • 114

5 Answers5

11

You can get all the strings in strings.xml via reflection, and filter out only the ones you need, like so:

for (Field field : R.string.class.getDeclaredFields())
{
  if (Modifier.isStatic(field.getModifiers()) && !Modifier.isPrivate(field.getModifiers()) && field.getType().equals(int.class))
  {
    try
    {
      if (field.getName().startsWith("tts_"))
      {
        int id = field.getInt(null);
        // do something here...
      }
    } catch (IllegalArgumentException e)
    {
      // ignore
    } catch (IllegalAccessException e)
    {
      // ignore
    }
  }
}
Logan Pickup
  • 2,294
  • 2
  • 22
  • 29
  • 2
    I haven't tried this myself, but provided that it works, THIS is the answer to the question, not the accepted one, which would only work in the ridiculous case where the names tts_1, tts_2, etc were acceptable. – matteo Oct 05 '14 at 18:42
  • Could you please specify which Field class is this? Is it java.lang.reflect.Field? – matteo Oct 05 '14 at 18:44
  • 1
    Yes, it's java.lang.reflect.Field. It should be easy to find, since it's the return type of `class.getDeclaredFields()` – Logan Pickup Oct 06 '14 at 11:10
  • Is it possible to get the strings of all modules (each R file exists in a different package) ? And, how do I get it for each language? – android developer Mar 15 '17 at 09:54
  • @androiddeveloper Yes, but you must know ahead of time (i.e. hard-code) all the different R classes in each package (e.g. `for (Field field : com.example.foo.R.string.class.getDeclaredFields())`). There are ways around that too, but they are substantially more complicated than this. – Logan Pickup Mar 15 '17 at 18:28
  • @androiddeveloper To get it for each language, you have to play around with resources after you have the list of IDs; you will need to call `Context.createConfigurationContext()` to create a new context for each locale (you can call `Context.getAssets().getLocales()` to find out what languages you have), and use that context to retrieve the resources for each ID you find using the method above, – Logan Pickup Mar 15 '17 at 18:35
  • @LoganPickup I see. Can you please share this answer here, then: http://stackoverflow.com/q/42806443/878126 ? – android developer Mar 16 '17 at 07:47
8

You can give them all (while defining) the resource name as "prefix"+(1..n). And in the code use,

int resid=<constant>;
for(i=1;resid!=0;i++){
        resid = this.getResources().getIdentifier("prefix"+i, "strings", this.getPackageName());
}
Blackbelt
  • 156,034
  • 29
  • 297
  • 305
Raviteja Andy
  • 224
  • 1
  • 7
2

You could put these TTS strings into a TypedArray.

Lawrence D'Oliveiro
  • 2,768
  • 1
  • 15
  • 13
0

you can use this code:

String[] strings = getResources().getAssets().list("string");
for (int i = 0; i < strings.length; i++) {
                Log.d("aaa ", strings[i]);
            }

to iterate through other resources like fonts,... just replace string with folder name.

-1

In all my projects, i just observed that the value of strings in R.java starts with 0x7f050000 and it counts upwards, like 0x7f050001, 0x7f050002, 0x7f050003,....

You could just ++ them :D

Hope it helps :)

Blackbelt
  • 156,034
  • 29
  • 297
  • 305
Vishnu Mohan G
  • 622
  • 1
  • 7
  • 14
  • 1
    You cannot assume that it starts from 0x7f050000 if your code hase arrays.xml attr.xml than sometimes it varies.. you are correct that it gives incremental ids but lowest id you can not assume. – Brijesh Masrani Dec 22 '12 at 07:51