I am trying to use getString()
to get an String from resources to assign it to an String array before my activity is created:
private static final String[] MenuNames = {
Resources.getSystem().getString(R.string.LCMeterMenu),
Resources.getSystem().getString(R.string.FrecMenu),
Resources.getSystem().getString(R.string.LogicAnalyzerMenu),
"Prueba con achartengine",
Resources.getSystem().getString(R.string.BrazoMenu)
};
When I use Resources.getSystem().getString(R.string.LCMeterMenu)
, Eclipse doesn't complain but I get an error at runtime:
Caused by: android.content.res.Resources$NotFoundException: String Resource ID #0x7f0a000a
But if I put inside onCreate()
:
Log.i("StringR", "String: " + getString(R.string.LCMeterMenu));
I get the String but I can't assign it to the final String I defined before. If I use only getString()
before onCreate()
I get and static error message. How can I use resources before onCreate()
for global variables?
The following is a working approach to initialize
static final
variables in android from XML, such asstrings.xml
.1.
MyApplication.java
2.
AndroidManifest.xml
3. Your application code, e.g. Activity
For working examples refer to
AbstractApplication
andPreferencesServiceSharedPreferences
.Note that this approach also has its downsides:
MyApplication.getContext()
is wrapped in another method. As it is a static method, overriding it in testing code is not simple. But you could use a framework such as Powermock for this purpose.NullPointerException
s. As soon as the context isnull
(e.g. in your testing code) the application code crashes. One option to overcome this, is to do the initialization in a constructor, where you could react togetContext()
returningnull
(see example).Whatever you get by the
getString(int resId)
will already be a constant for your application. Why do you have to keep it in anotherfinal static
variable. You can read it like that whenever you want, right?You cannot initialize a
static final
field from resources; the field needs to be initialized at the time the class is initialized and that happens before the application resources have been bound at run time. (By the way, the reason you cannot useResources.getSystem()
is that theResources
object you obtain that way contains only system resources, not any application resources.)If you need those strings available before the application resources are bound, the only practical thing to do is to put the strings into the code directly. However, the "Android way" would be to organize your code so initialization only needs to happen during (or after)
onCreate()
. Just initialize the string array inonCreate()
and don't worry about making the fields static or final.If you don't want the string array to be associated with a particular activity, then you can subclass
Application
and read the array from resources inside the application class'sonCreate()
method. (You also need to declare your custom application class in the manifest.) However, the docs recommend against such an approach. (Since the array is private, I suspect that it is closely tied to a single activity anyway, so the use of anApplication
subclass doesn't seem warranted.)An alternative is to declare a singleton class for your array. The singleton accessor function then needs a
Context
so it can retrieve the resources if necessary:(This assumes the string data are defined in a
<string-array>
resource like @JaiSoni suggested in his answer.) Once again, the member field cannot be declaredfinal
.Another approach could be to initialize the static array with resource identifiers (which are already available as opposed to the resources themselves).
This way, you can defer the loading of resources to when they are actually available:
No, you can't use Resources before
onCreate()
. You can get the instance of Resources inonCreate()
by usinggetResources()
where you can get all the Strings. Also the strings are already declared as static by defining them in thestrings.xml
.Pseudo code for accessing the Resources,