コンテキストまたはアクティビティ外のgetString


260

R.stringハードコードされた文字列をコードから除外するのに非常に優れていることがわかったので、アプリケーションのモデルと連携して出力を生成するユーティリティクラスでそれを使い続けたいと思います。たとえば、この場合、アクティビティの外部のモデルからメールを生成しています。

getString外でContextも使えActivityますか?私は現在の活動を渡すことができると思いますが、それは不必要なようです。私が間違っていたら訂正してください!

編集:使用せずにリソースにアクセスできますContextか?


4
文字列を使用するクラスにコンテキストを渡すことにより、アプリで使用されている言語(en、esなど)に関する情報も渡されます。したがって、strings.xmlが2つある場合、どちらを使用するかがわかります
スポーツ

回答:


439

はい、 `Context`を使用せずにリソースにアクセスできます

以下を使用できます。

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

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

ローカルリソースについては、このソリューションを使用してください。ささいなことではありませんが、機能します。


17
システムリソースとはどういう意味ですか?strings.xmlはシステムリソースですか?私にとってはそれは動作しません、と言うリソースを見つけることができません。
キルホフ2013年

6
システムリソースは、デバイス上のAndroidに属しています。strings.xmlはアプリケーションにのみ属します。stackoverflow.com/a/4391811/715269ソリューションを探す
Gangnus 2013年

3
これは、文字列にアクセスするときのこれらのFactoryクラスのエレガントなソリューションです。私はどこでもコンテキストを渡すことを楽しんでいない。文字列をグローバルに保存したいだけの場合は、これは不要な混乱です。
Jay Snayder 2013

1
これは、コンテキストをクラスに渡して使用するよりも効率的ですか?
SoliQuiD 2015年

5
このエラーが発生するandroid.content.res.Resources$NotFoundException: String resource ID #0x7f0f0061
エブラヒムカリミ

108

残念ながら、任意の文字列リソースにアクセスできる唯一の方法は、Context(つまり、ActivityまたはService)を使用することです。この場合、私が通常行っていることは、呼び出し側にコンテキストを渡すことを要求するだけです。


4
先端をありがとう!私はこれを試してみましたが、試したときにコンパイルエラーが発生しました:ctx.getString(ctx.R.string.blah);
SapphireSun

タイプのutilメソッドに引数を作成してContext、アクティビティまたはサービスから使用できるようにします。
MatrixFrog 2010年

2
あなたはを必要とせずctx.R.string.blah、ただ使うR.string.blah
Pentium10

2
どこからsymbol not found error来るのかはわかりませんRが、クラスの上にインポートしたことを確認してください。
Pentium10 2010年

11
答えはFALSEです。次のものです。:-)
Gangnus 2012年

33

ではMyApplication、次のように拡張されますApplication

public static Resources resources;

MyApplicationさんonCreate

resources = getResources();

これで、アプリケーションのどこからでもこのフィールドを使用できます。


サービスを通じて機能しますか?(特にAndroidがアプリを強制終了してサービスのみを開始する場合)
Atul

1
はい。AndroidはApplication.onCreateを呼び出してコードの実行を開始し、その後サービスを実行します。
konmik

23

ところで、シンボルが見つからないというエラーの原因の1つは、IDEがandroid.Rをインポートしたことです。あなたのものではなくクラス。import android.Rを変更するだけです。your.namespace.Rインポートします。

したがって、異なるクラスで文字列を表示するための2つの基本的なこと:

//make sure you are importing the right R class
import your.namespace.R;

//don't forget about the context
public void some_method(Context context) {
   context.getString(R.string.YOUR_STRING);
}

19

ユニークなアプローチ

App.getRes().getString(R.string.some_id)

これはアプリのどこでも機能します。(アプリ内のUtilクラス、Dialog、Fragmentまたは任意のクラス

(1)Applicationクラスを作成または編集します(既に存在する場合)。

import android.app.Application;
import android.content.res.Resources;

public class App extends Application {
    private static App mInstance;
    private static Resources res;


    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
        res = getResources();
    }

    public static App getInstance() {
        return mInstance;
    }

    public static Resources getResourses() {
        return res;
    }

}

(2)名前フィールドをmanifest.xml <applicationタグに追加します。

<application
        android:name=".App"
        ...
        >
        ...
    </application>

これで準備完了です。App.getRes().getString(R.string.some_id)アプリのどこでも使用できます。


1
私は個人的にこのアプローチが好きです。コードのどこからでもカスタム文字列リソースを取得するのに便利です。
checkmate711

このソリューションにセキュリティ上の問題はありますか?
nibbana

@ user1823280いいえ、私は思いません。
ケムラジ

完璧なソリューション
Yasiru Nayanajith

4

アクティビティで使用するクラスがあり、そのクラスのリソースにアクセスしたい場合は、コンテキストをクラスのプライベート変数として定義し、コンストラクターで初期化することをお勧めします。

public class MyClass (){
    private Context context;

    public MyClass(Context context){
       this.context=context;
    }

    public testResource(){
       String s=context.getString(R.string.testString).toString();
    }
}

あなたの活動のクラスのインスタントを作る:

MyClass m=new MyClass(this);

0

これによりapplicationContext、どこからでもアクセスapplicationContextできるようになり、それを使用できる場所ならどこにでもアクセスできるようになります。ToastgetString()sharedPreferences、など

シングルトン:

package com.domain.packagename;

import android.content.Context;

/**
 * Created by Versa on 10.09.15.
 */
public class ApplicationContextSingleton {
    private static PrefsContextSingleton mInstance;
    private Context context;

    public static ApplicationContextSingleton getInstance() {
        if (mInstance == null) mInstance = getSync();
        return mInstance;
    }

    private static synchronized ApplicationContextSingleton getSync() {
        if (mInstance == null) mInstance = new PrefsContextSingleton();
        return mInstance;
    }

    public void initialize(Context context) {
        this.context = context;
    }

    public Context getApplicationContext() {
        return context;
    }

}

Applicationサブクラスでシングルトンを初期化します。

package com.domain.packagename;

import android.app.Application;

/**
 * Created by Versa on 25.08.15.
 */
public class mApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ApplicationContextSingleton.getInstance().initialize(this);
    }
}

私が間違っていない場合、これはどこでもapplicationContextへのフックを提供します。これを呼び出すとApplicationContextSingleton.getInstance.getApplicationContext(); 、アプリケーションを閉じるときにこれをとにかく行うので、いつでもこれをクリアする必要はありません。

AndroidManifest.xmlこのApplicationサブクラスを使用するように更新することを忘れないでください:

<?xml version="1.0" encoding="utf-8"?>

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.domain.packagename"
    >

<application
    android:allowBackup="true"
    android:name=".mApplication" <!-- This is the important line -->
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:icon="@drawable/app_icon"
    >

ここで何か問題がありましたらお知らせください、ありがとうございます。:)


0

ケムラジの反応からの最善のアプローチ:

アプリクラス

class App : Application() {

    companion object {
        lateinit var instance: Application
        lateinit var resourses: Resources
    }


    // MARK: - Lifecycle

    override fun onCreate() {
        super.onCreate()
        instance = this
        resourses = resources
    }

}

マニフェストでの宣言

<application
        android:name=".App"
        ...>
</application>     

定数クラス

class Localizations {

    companion object {
        val info = App.resourses.getString(R.string.info)
    }

}

使用する

textView.text = Localizations.info

0

コンテキストアクティビティなしこのようなものを使用することをお勧めします:

Resources.getSystem().getString(R.string.my_text)

0

どういうわけか、静的な値を格納するハッキーなソリューションが気に入らなかったので、少し長くなりますが、同様にテストできるクリーンなバージョンを考え出しました。

それを行うための2つの可能な方法が見つかりました-

  1. 文字列リソースが必要なクラスに、context.resourcesをパラメーターとして渡します。かなりシンプル。パラメータとして渡すことができない場合は、セッターを使用します。

例えば

data class MyModel(val resources: Resources) {
    fun getNameString(): String {
        resources.getString(R.string.someString)
    }
}
  1. データバインディングを使用する(ただし、フラグメント/アクティビティが必要)

お読みになる前に:このバージョンでは Data binding

XML-

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>
    <variable
        name="someStringFetchedFromRes"
        type="String" />
</data>

<TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{someStringFetchedFromRes}" />
</layout>

アクティビティ/フラグメント-

val binding = NameOfYourBinding.inflate(inflater)
binding.someStringFetchedFromRes = resources.getString(R.string.someStringFetchedFromRes)

場合によっては、モデルのフィールドに基づいてテキストを変更する必要があります。そのため、そのモデルもデータバインドします。アクティビティ/フラグメントはモデルについて知っているため、値をフェッチして、それに基づいて文字列をデータバインドできます。


0

Kotlinでこれを行うには、Applicationを拡張するクラスを作成し、そのコンテキストを使用してコード内の任意の場所でリソースを呼び出します。

Appクラスは次のようになります

 class App : Application() {
    override fun onCreate() {
        super.onCreate()
        context = this
    }

    companion object {
        var context: Context? = null
            private set
    }
}

AndroidManifest.xmlでアプリケーションクラスを宣言する(非常に重要)

<application
        android:allowBackup="true"
        android:name=".App" //<--Your declaration Here
        ...>
        <activity
            android:name=".SplashActivity"  android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".MainActivity"/>
    </application>

たとえば文字列ファイルにアクセスするには、次のコードを使用します

App.context?.resources?.getText(R.string.mystring)

アプリケーションコンテキストはシングルトンであり、プロセスの開始時に初期化されるため、実行時にプログラムでロケールを変更すると、これは機能しません。
Szörényiアダム

-2

これが私がしたことです、あなたのMainActivityで、以下に示すようにコンテキストの静的変数を作成してください:

public static Context mContext;

そして、onCreate()でmContextをこれに初期化します。

mContext = this;

次に、コンテキストにアクセスしたいファイルで、

private Context context = MainActivity.mContext;

これで、次の方法で文字列リソースを取得できます。

String myString = context.getResources().getString(R.string.resource_id);

-8

使用 getContext().getApplicationContext().getString(R.string.nameOfString); しました。


14
getContext()どこでも利用できると思いますか?!
Hamzeh Soboh 2015年

1
getContext()はアクティビティクラスとフラグメントクラスでのみ使用できるため、これは質問に対する回答を提供しません
Umar Ata
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.