Application throws an exception
android.content.res.Resources$NotFoundException: String resource ID
My case wasn't that common (since given ID does exist). I asked this question to answer it by myself.
Please see below my answer why could this happen and why it happend for me.
You maybe already found that this error happens when you are trying to set some integer as a string like:
somewhere in the code some_variable
was declared as int
and you want to show its value so you are trying to set it to some_textview
using setText()
method:
int some_variable = 0;
TextView txtView = (TextView) findViewById(R.id.someTextView);
... some code/calculations etc...
txtView.setText(some_variable); // exception! some_variable is an int value
also it could be a result returned by any method which returns int as a result, like:
txtView.setText(someString.length());// exception! String.length() returns an int value
txtView.setText(someSet.size());// exception! Set.size() returns an int value
etc.
these causes the Resources$NotFoundException
cuz there is no String
resource with such number (id).
As you most probably know at every build time there is a R.java
file being created in build folder. This file contains static variables where every declared in string.xml String
has its own unique id with some int value and this id you use in code as R.string.id. This is the reason of exception - system will try to find R.string.id string corresponding to given value but obviously fails in most cases. Also this is a reason why setText() accepts integer values and IDE don't warn you.
In some cases it could happen that your some_variable
by chance will have a value which corresponds to some id. These are tricky cases because no exception will be thrown and you will see some unexpected text (actually corresponding to R.string.id) instead of variable value.
The solution to this issue is simple (if some_variable
's value must be shown):
txtView.setText(String.valueOf(some_variable));
There are also a number of people who are trying to set the int
value in the same manner to the Toast
message like:
int some_variable = 0;
... some code/calculations etc...
Toast.makeText(this, some_variable, Toast.LENGTH_LONG).show();
Toast.makeText(getBaseContext(), someSet.size(), Toast.LENGTH_LONG).show();
The fix is the same:
int some_variable = 0;
... some code/calculations etc...
Toast.makeText(this, String.valueOf(some_variable), Toast.LENGTH_LONG).show();
Toast.makeText(getBaseContext(), String.valueOf(some_Set.size()), Toast.LENGTH_LONG).show();
You maybe met approach which uses Integer(some_variable).toString()
method. Its not bad. However this means 1 extra operation (wrapping int value to Integer) will be applied and that only integer value could be used (or NumberFormatException
will be thrown) while for String.valueOf(some_variable)
value type doesn't matter, it works for any type of value, including all primitives (float, double, byte, long etc) and will never throw any exception.
Also there are some other cases - rare cases are described here and the point is to clean the project in IDE.
In case if you are pretty sure you don't pass any integers in a manner described above and moreover this happens with released app and did not happen while developing it could be a Locale
case. If your app has Locale
depending String
resources and when you tested it you probably did it using your region specific Locale
device(s) and thus no issues was detected. However (bear in mind!) in such case you must provide a default strings.xml
located in res\values
folder of a project and if you missed it this is the case. Assume some user, lets say, from a Germany (who's device default Locale
is DE) tries to run such app which only has strings.xml
in folders values-en
and values-it
(but there is no strings.xml
in values
nor in values-de
folders). In this case app will try to locate values-de\strings.xml
first but fails, then it will try to use default values\strings.xml
and fails once again so it will crash throwing Resources$NotFoundException
.
The fix for this issue is, like I mentioned before, to provide a default strings.xml
in res\values
folder of a project so for any unsupported locale the default one will be used (usually english). Another way is to set a proper default locale for your app at run time (in Application extended class for instance) if it runs on a device with unsupported locale, like (assume you want to use en
locale by default):
Locale locale = getAppLocale(context);
String localeLang = locale.getLanguage();
// default locale is EN but available are EN and RU
if (!localeLang.equalsIgnoreCase("en") && !localeLang.equalsIgnoreCase("ru")) {
locale = new Locale("en");
Configuration config = new Configuration();
config.locale = locale;
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
}