アプリケーションが例外をスローする
android.content.res.Resources$NotFoundException: 文字列リソース ID
私のケースはそれほど一般的ではありませんでした (特定の ID が存在するため)。私は自分で答えるためにこの質問をしました。
なぜこれが起こるのか、なぜそれが私に起こったのか、私の答えの下を見てください。
some_variable
コードのどこかで次のように整数を文字列として設定しようとすると、このエラーが発生することが既にわかっているかもしれませint
ん。some_textview
setText()
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
また、次のように、結果として int を返す任意のメソッドによって返される結果である可能性もあります。
txtView.setText(someString.length());// exception! String.length() returns an int value
txtView.setText(someSet.size());// exception! Set.size() returns an int value
等
これらは、そのような番号 (id) を持つリソースResources$NotFoundException
がないため、原因となります。おそらくご存知のように、ビルドのたびにビルド フォルダーにファイルが作成されます。このファイルには静的変数が含まれており、string.xml で宣言されたすべての変数には、いくつかの int 値を持つ独自の一意のIDがあり、このIDをコードで R.string として使用します。id . これが例外の理由です。システムは R.string を見つけようとします。指定された値に対応するid文字列ですが、ほとんどの場合明らかに失敗します。また、これが setText() が整数値を受け入れ、IDE が警告しない理由でもあります。場合によっては、偶然にIDに対応する値を持つことがあります。String
R.java
String
some_variable
. 例外はスローされず、変数値の代わりに予期しないテキスト (実際には R.string. idに対応する) が表示されるため、これらはトリッキーなケースです。
この問題の解決策は簡単です (some_variable
の値を表示する必要がある場合):
txtView.setText(String.valueOf(some_variable));
次のようなメッセージint
に同じ方法で値を設定しようとしている人もたくさんいます。Toast
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();
修正は同じです:
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();
Integer(some_variable).toString()
メソッドを使ったアプローチに出会ったかもしれません。悪くない。ただし、これは 1 つの余分な操作 (int 値を Integer にラップする) が適用され、整数値のみを使用できる (またはNumberFormatException
スローされる) ことを意味しますが、String.valueOf(some_variable)
値の型は問題ではなく、すべてのプリミティブを含む任意の型の値に対して機能します。 (float、double、byte、long など) であり、例外をスローすることはありません。
また、他にもいくつかのケースがあります。ここではまれなケースについて説明します。要点は、IDE でプロジェクトをクリーンアップすることです。
上記の方法で整数を渡さないことが確実であり、さらにこれがリリースされたアプリで発生し、開発中には発生しなかったLocale
場合は、ケースである可能性があります。あなたのアプリがLocale
依存している場合String
リソースと、それをテストしたときに、おそらく地域固有Locale
のデバイスを使用してテストしたため、問題は検出されませんでした。ただし (心に留めておいてください!) そのような場合、プロジェクトのフォルダーにstrings.xml
あるデフォルトを提供する必要があります。res\values
たとえば、ドイツのユーザー (デバイスのデフォルトLocale
は DE) がstrings.xml
、フォルダーvalues-en
とフォルダーのみを含むvalues-it
(ただし、フォルダーstrings.xml
内values
もvalues-de
フォルダーもありません) そのようなアプリを実行しようとするとします。この場合、アプリはvalues-de\strings.xml
最初に検索しようとしますが失敗し、次にデフォルトを使用しようとしてvalues\strings.xml
もう一度失敗するため、 throwing でクラッシュしResources$NotFoundException
ます。
この問題の修正は、前に述べたように、デフォルトを提供することstrings.xml
ですres\values
サポートされていないロケールの場合、デフォルトのロケールが使用されます (通常は英語)。もう 1 つの方法は、次のように、サポートされていないロケールのデバイスでアプリを実行する場合に、実行時にアプリに適切な既定のロケールを設定することです (たとえば、アプリケーション拡張クラスen
)。
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());
}