静的コンテキストからリソースコンテンツを取得するにはどうすればよいですか?


168

ウィジェットでxml他のほとんどのことを行う前にファイルから文字列を読み取りたいsetTextので、アクティビティオブジェクトを呼び出さずにそれを行うにはどうすればよいgetResources()ですか?

回答:


373
  1. のサブクラスを作成する Applicationたとえばのしますpublic class App extends Application {
  2. タグのandroid:name属性を<application>AndroidManifest.xml新しいクラスを指すように設定します。例:android:name=".App"
  3. ではonCreate()アプリのインスタンスの方法、あなたのコンテキストの保存(例えばthis)という名前の静的フィールドにmContext、このフィールドを返す静的メソッドを作成して、例えばgetContext()

これは次のようになります。

public class App extends Application{

    private static Context mContext;

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;
    }

    public static Context getContext(){
        return mContext;
    }
}

これでApp.getContext()、コンテキストを取得したいときにいつでもgetResources()(またはApp.getContext().getResources())を使用できます。


9
アプリケーションのインスタンスは動的な値ではありませんが、@ Gangnusはどうですか?いずれにせよ-私はAndroidの静力学に頼ることが頭痛の種に過ぎないという難しい方法を見つけました。「今では見えますが、見えなくなりました」
Bostone

18
これが「ハック」だとは思わない。私はそれを使用していますが(ローカライゼーションを外部化しようとしていたので、このソリューションを提供してくれてありがとう)、この悪い感じがします。
Illiax 2013

8
アプリのすべての静的メソッドの最初のパラメーターとして単にコンテキストを渡すよりも良いですか、悪いですか?前者はハックに感じますが、後者は不必要に繰り返します。
Dave

12
ドキュメントは、「通常、アプリケーションをサブクラス化する必要はありません。ほとんどの状況で、静的シングルトンは、よりモジュール的な方法で同じ機能を提供できます。シングルトンがグローバルコンテキストを必要とする場合(たとえば、ブロードキャストレシーバーを登録するため)、取得する関数シングルトンを最初に構築するときに、Context.getApplicationContext()を内部的に使用するContextを指定できます。〜developer.android.com/reference/android/app/Application.html
デヴィッド・D C Eフレイタス

25
メモリのリークを回避するには、コンテキストをWeakReferenceに保存することをお勧めします。private static WeakReference <Context> mContext; public static Context getContext(){return mContext.get(); これは、アプリがクラッシュし、静的コンテキストをnullに設定できない場合に役立ちます(WeakReferenceはガベージコレクションされる可能性があります)。
FrankKrumnow、2015年

102

システムリソースのみ!

使用する

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

静的定数宣言でも、アプリケーションのどこでも使用できます!


2
カッコいい。私は通常気分を害しません...誰かが大文字を使うときだけです:P冗談です。まあ、あなたの標準は文字列やドローアブルのようないくつかのリソースで機能します...しかし、ドキュメントが言うように、それは方向測定などのようなものにはうまく機能しません。そして、そして最も重要なことに、これはあなたが必要な場合に役立つグローバルコンテキスト(Toastたとえば、SharedPreferenceラテン語の教師が言うように、インスタンスの取得、インスタンスの取得、データベースのオープンなど)。
クリスティアン

1
あなたはそれで全世界の平和に勝つことさえできません:-)。しかし、それはここで質問によって設定された問題を解決するのに役立ちます。私はそれがすべてのタスクを解決すると言っているのではなく、アプリケーションのほぼすべての場所でそのタスクを解決しているだけです。私はそのようなソリューションを10か月間検索しました-私は常にAndroidを使用しています。そして今、それを見つけました。
Gangnus、2012年

18
ここで注意する必要があります。この方法を使用してアプリのリソースを見つけようとしないでください。詳細をお読みください:システムリソースのみ(アプリケーションリソースなし)へのアクセスを提供し、現在の画面に対して構成されていない(寸法単位を使用できない、方向に基づいて変化しないなど)グローバル共有リソースオブジェクトを返します。
Bostone

4
@ DroidIn.net引用:「ただし、システムリソースのみ!」私は/ * sigh / *を知っています
Gangnus

1
私はそれを使用して例外を受け取りました:android.content.res.Resources $ NotFoundException:文字列リソースID
vinidog '29

6

私のKotlinソリューションは、静的なアプリケーションコンテキストを使用することです。

class App : Application() {
    companion object {
        lateinit var instance: App private set
    }

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

そして、私がどこでも使用するStringsクラス:

object Strings {
    fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
        return App.instance.getString(stringRes, *formatArgs)
    }
}

したがって、リソース文字列を取得するクリーンな方法を持つことができます

Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")

この回答は削除しないでください。1つ残しておきます。


シンプルでクリーンなソリューション。コードを共有していただきありがとうございます。
Jeehut

ありがとう!これは既知の解決策ですStringsが、役に立ちました。
CoolMind

4

別の可能性もあります。次のようなリソースからOpenGlシェーダーをロードします。

static private String vertexShaderCode;
static private String fragmentShaderCode;

static {
    vertexShaderCode = readResourceAsString("/res/raw/vertex_shader.glsl");
    fragmentShaderCode = readResourceAsString("/res/raw/fragment_shader.glsl");
}

private static String readResourceAsString(String path) {
    Exception innerException;
    Class<? extends FloorPlanRenderer> aClass = FloorPlanRenderer.class;
    InputStream inputStream = aClass.getResourceAsStream(path);

    byte[] bytes;
    try {
        bytes = new byte[inputStream.available()];
        inputStream.read(bytes);
        return new String(bytes);
    } catch (IOException e) {
        e.printStackTrace();
        innerException = e;
    }
    throw new RuntimeException("Cannot load shader code from resources.", innerException);
}

ご覧のとおり、クラスのパス/res/... Change aClassにある任意のリソースにアクセスできます。これは、テストでリソースをロードする方法(androidTests)


1
アクティビティがない場合に機能する唯一の解決策(アプリケーションを拡張できるクラスのないプラグインを開発する)。ありがとう+1
itaton 2018

3

シングルトン:

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"
    >

これで、どこからでもApplicationContextSingleton.getInstance()。getApplicationContext()。getResources()を使用できるようになりました。また、アプリケーションサブクラスが使用できない非常に少数の場所でも使用できます。

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


2

別の解決策:

非静的外部クラスに静的サブクラスがある場合、外部クラスの作成時に初期化する外部クラスの静的変数を介してサブクラス内からリソースにアクセスできます。お気に入り

public class Outerclass {

    static String resource1

    public onCreate() {
        resource1 = getString(R.string.text);
    }

    public static class Innerclass {

        public StringGetter (int num) {
            return resource1; 
        }
    }
}

私はそれを、I8Nのために役立つ私のFragmentActivity内の静的FragmentPagerAdapterのgetPageTitle(int position)関数に使用しました。


2

ショートカット

(@Cristianが答えたように)のApp.getRes()代わりに使用しますApp.getContext().getResources()

コードのどこででも簡単に使用できます!

だからここはあなたがどこからでもリソースにアクセスできるユニークなソリューションですUtil class

(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)コードのどこでも使用できます。


0

もっと方法があると思います。しかし、時々、私はこのソリューションを使用しています。(完全なグローバル):

    import android.content.Context;

    import <your package>.R;

    public class XmlVar {

        private XmlVar() {
        }

        private static String _write_success;

        public static String write_success() {
            return _write_success;
        }


        public static void Init(Context c) {
            _write_success = c.getResources().getString(R.string.write_success);
        }
    }
//After activity created:
cont = this.getApplicationContext();
XmlVar.Init(cont);
//And use everywhere
XmlVar.write_success();

0

静的関数からopenGL ESのシェーダーをロードします。

ファイル名とディレクトリ名には小文字を使用する必要があります。小文字を使用しないと、操作が失敗します

public class MyGLRenderer implements GLSurfaceView.Renderer {

    ...

    public static int loadShader() {
        //    Read file as input stream
        InputStream inputStream = MyGLRenderer.class.getResourceAsStream("/res/raw/vertex_shader.txt");

        //    Convert input stream to string
        Scanner s = new Scanner(inputStream).useDelimiter("\\A");
        String shaderCode = s.hasNext() ? s.next() : "";
    }

    ...

}

0
public Static Resources mResources;

 @Override
     public void onCreate()
     {
           mResources = getResources();
     }

さて、問題は、getResources()がコンテキストを必要とすることです。これはおそらく、(ここで、あなたがのonCreate()メソッドを掲載)本当に「活動オブジェクトなし」のsoltutionされないように
トビアス・ライヒ

0

私はAPIレベル27を使用しており、約2日間も苦労して最高のソリューションを見つけました。アクティビティまたはアプリケーションから派生していないクラスからxmlファイルを読み取りたい場合は、次のようにします。

  1. testdata.xmlファイルをアセットディレクトリ内に配置します。

  2. 次のコードを記述して、testdataドキュメントを解析します。

        InputStream inputStream = this.getClass().getResourceAsStream("/assets/testdata.xml");
    
        // create a new DocumentBuilderFactory
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        // use the factory to create a documentbuilder
        DocumentBuilder builder = factory.newDocumentBuilder();
        // create a new document from input stream
        Document doc = builder.parse(inputStream);

-1

静的関数を実装するクラスでは、このクラスからprivate \ publicメソッドを呼び出すことができます。private \ publicメソッドはgetResourcesにアクセスできます。

例えば:

public class Text {

   public static void setColor(EditText et) {
      et.resetColor(); // it works

      // ERROR
      et.setTextColor(getResources().getColor(R.color.Black)); // ERROR
   }

   // set the color to be black when reset
   private void resetColor() {
       setTextColor(getResources().getColor(R.color.Black));
   }
}

そして、他のclass \ activityから、あなたは呼び出すことができます:

Text.setColor('some EditText you initialized');

-1

コンテキストがある場合、私は中を意味します。

public void onReceive(Context context, Intent intent){

}

このコードを使用してリソースを取得できます。

context.getResources().getString(R.string.app_name);

2
質問のタイトルは静的なコンテキストで述べています。あなたの答えはカバーしません。
Rune Schjellerup Philosof 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.