2016-04-01 11 views
0

私はAndroidアプリを書いていますので、私はいつものように私のstrings.xmlにすべての文字列を持っており、Androidの公式ドキュメントごとに述べています。文字列を使用したAndroidの頭痛:アプリ内のすべての文字列を集中化するにはどうすればよいですか?

ここまでは問題ありませんが、Javaの「標準」クラスで文字列を使用する場合に問題が発生します。すなわち、Email.javaにこの文字列を言わせて:

public static final String EMAIL_NOT_VALID = "The email address provided is not valid."; 

あなたは、私がstrings.xmlにこの文字列を配置して行うことができると言うことができます。

getResources().getString(R.string.invalid_email_message) 

このアプローチの問題は、私が合格することを余儀なくされるということです私のアプリ内のすべての単一のJavaオブジェクトへのAndroid Contextは、テストに関してはこれが関係するすべての疑惑の問題を伴います。

したがって、コンテキストを渡さずにこれを行うことは可能ですか?または、別の文字列を持つ2つのファイル(strings.xmlxyz.java)が必要ですか

I'veは)運なしでStackOverflowの上で時間事前に

おかげでこの質問への答えを探して。

+1

あなたはコンテキストを提供すること(シングルトン)まで残し、これを抽象化し、文字列を取得するためにそれを呼び出すシングルトンを持ってもらえますか?シングルトンにコンテキストを公開させて、テスト/モックのために注入することもできます。 – npinti

+0

@ankitaggarwal質問をお読みください。私はその解決策を望んでいないと述べた。 –

+0

@npinti本当に興味深い。もう少し詳しく説明してください。 –

答えて

1

あなたはassetsフォルダに文字列を入れて試すことができ、それはあなたがすなわち「ローカリゼーション」という名前の新しいフォルダを作成し、ここにstrings_enのようなあなたのローカライゼーション・ファイルを保存することができますYourProject/app/src/main/assets内部資産で作成する必要があり、このファイルストア内のすべてのJSONオブジェクト"{"key" : "value"}の文字列をすべて処理したら、すべての言語を管理するクラスを作成する必要があります。

public class LocalizationManager { 

    private static LocalizationManager mInstance = null; 
    public String currentLanguage = ""; 
    JSONObject currentLanguageObject = new JSONObject(); 
    private AssetManager assetManager = BaseApplication.getInstance().getAssets(); // BaseApplication is just a class that extends Application class 

    private LocalizationManager() { 
    } 

    public static LocalizationManager getInstance() { 
     if (mInstance == null) { 
      mInstance = new LocalizationManager(); 
     } 
     return mInstance; 
    } 

    private boolean assetExists(String path) { 
     boolean bAssetOk = false; 
     try { 
      InputStream stream = assetManager.open(path); 
      stream.close(); 
      bAssetOk = true; 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     return bAssetOk; 
    } 

    public String getLocalizedString(String string) { 
     String language = BaseApplication.getInstance().getLanguage(); 
     if (!currentLanguage.equalsIgnoreCase(language)) { 
      if (assetExists("localization/strings_" + language)) { 
       InputStream input; 
       try { 
        input = assetManager.open("localization/strings_" + language); 
        int size = input.available(); 
        byte[] buffer = new byte[size]; 
        input.read(buffer); 
        input.close(); 
        String responseString = new String(buffer); 
        Object json; 
        try { 
         json = new JSONTokener(responseString).nextValue(); 
         if (json instanceof JSONObject) { 
          currentLanguageObject = (JSONObject) json; 
          currentLanguage = language; 
          return currentLanguageObject.optString(string, string); 
         } 
        } catch (JSONException e) { 
         return string; 
        } 
       } catch (IOException e) { 
        return string; 
       } 
      } 
     } else { 
      return currentLanguageObject.optString(string, string); 
     } 
     return string; 
    } 
} 

次に、どのクラスでもLocalizationManager.getInstance().getLocalizedString("Your string key")を呼び出すことができます。この方法では、アプリケーション内で「言語を変更」オプションを追加し、例えばenという値を環境設定に格納し、言語を動的に変更する必要があります。ここで私はそれをやった方法です:

public void setLanguage(String language) { 
    mPreferences = getSharedPreferences(LANGUAGE_KEY_FOR_PREFS, MODE_PRIVATE); 
    SharedPreferences.Editor editor = mPreferences.edit(); 
    editor.putString("Language", language); 
    editor.apply(); 
    mListener.onLanguageChanged(); 
} 


public String getLanguage() { 
    mPreferences = getSharedPreferences(LANGUAGE_KEY_FOR_PREFS, MODE_PRIVATE); 
    return mPreferences.getString("Language", "en"); 
} 
+0

ありがとうございました!それが私が探していた戦略でした! –

+0

ようこそ) –

0

あなたは使用することができます。

Resources.getSystem().getString(android.R.string.somecommonstuff) 

を...どこでも、あなたのアプリケーションであっても静的定数の宣言で。残念ながら、これはシステムリソースのみをサポートしています。スタックオーバーフロー

+0

私は好きなように動作しません。その行はintを返しますが、適切なStringが必要です。同様に、私はstrings.xmlに入っている文字列を検出していません –

1

内のスレッドの1から

あなたのコードのクラスであなたの弦楽器、特にメッセージを保持しませんが。決して。あなたはそれを他の言語に翻訳することはできません。デバッガでのみ表示されるログメッセージを除いて、すべての文字列リソースを使用します。

あなたはGlobals.javaようなクラスを作成し、そこに

public static Context appContext; 

を入れて、あなたがして

Globals.appContext = getApplicationContext(); 

として(あなたのMainActivityの= "のonCreate")APPSTARTでこの静的を埋めることができどこにでもコンテキストがあります。 バックグラウンドから復帰したときにMainActivityのonResumeイベントでコンテキストを更新するようにしてください。

Android API全体でこの「問題」が表示されます.SQLiteOpenHelperにはコンテキストが必要です。すべてにはコンテキストが必要です。それはAndroidのゲームの一部です。

+0

非常に良い答え私の友人、それのためにありがとう。私はそれに行くつもりです。また、 Activity.javaクラスからのメッセージのみを表示する予定です。この戦略についてどう思いますか? –

関連する問題