getString Outside of a Context or Activity

JavaAndroidStringAndroid ResourcesAndroid Context

Java Problem Overview


I've found the R.string pretty awesome for keeping hardcoded strings out of my code, and I'd like to keep using it in a utility class that works with models in my application to generate output. For instance, in this case I am generating an email from a model outside of the activity.

Is it possible to use getString outside a Context or Activity? I suppose I could pass in the current activity, but it seems unnecessary. Please correct me if I'm wrong!

Edit: Can we access the resources without using Context?

Java Solutions


Solution 1 - Java

Yes, we can access resources without using Context
You can use:

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

... everywhere in your application, even in static constants declarations. Unfortunately, it supports the system resources only.

For local resources use this solution. It is not trivial, but it works.

Solution 2 - Java

Unfortunately, the only way you can access any of the string resources is with a Context (i.e. an Activity or Service). What I've usually done in this case, is to simply require the caller to pass in the context.

Solution 3 - Java

In MyApplication, which extends Application:

public static Resources resources;

In MyApplication's onCreate:

resources = getResources();

Now you can use this field from anywhere in your application.

Solution 4 - Java

##Unique Approach

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

> This will work everywhere in app. (Util class, Dialog, Fragment or > any class in your app)

(1) Create or Edit (if already exist) your Application class.

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 getRes() {
        return res;
    }

}

(2) Add name field to your manifest.xml <application tag.

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

Now you are good to go. Use App.getRes().getString(R.string.some_id) anywhere in app.

Solution 5 - Java

BTW, one of the reason of symbol not found error may be that your IDE imported android.R; class instead of yours one. Just change import android.R; to import your.namespace.R;

So 2 basic things to get string visible in the different class:

//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);
}

Solution 6 - Java

If you have a class that you use in an activity and you want to have access the ressource in that class, I recommend you to define a context as a private variable in class and initial it in constructor:

public class MyClass (){
    private Context context;

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

Making an instant of class in your activity:

MyClass m=new MyClass(this);

Solution 7 - Java

The best approach from the response of Khemraj:

App class

class App : Application() {

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


    // MARK: - Lifecycle

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

}

Declaration in the manifest

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

Constants class

class Localizations {

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

}

Using

textView.text = Localizations.info

Solution 8 - Java

This should get you access to applicationContext from anywhere allowing you to get applicationContext anywhere that can use it; Toast, getString(), sharedPreferences, etc.

The Singleton:

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;
    }

}

Initialize the Singleton in your Application subclass:

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);
    }
}

If I´m not wrong, this gives you a hook to applicationContext everywhere, call it with ApplicationContextSingleton.getInstance.getApplicationContext(); You shouldn´t need to clear this at any point, as when application closes, this goes with it anyway.

Remember to update AndroidManifest.xml to use this Application subclass:

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

Please let me know if you see anything wrong here, thank you. :)

Solution 9 - Java

You can do this in Kotlin by creating a class that extends Application and then use its context to call the resources anywhere in your code

Your App class will look like this

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

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

Declare your Application class in AndroidManifest.xml (very important)

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

To access e.g. a string file use the following code

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

Solution 10 - Java

Somehow didn't like the hacky solutions of storing static values so came up with a bit longer but a clean version which can be tested as well.

Found 2 possible ways to do it-

  1. Pass context.resources as a parameter to your class where you want the string resource. Fairly simple. If passing as param is not possible, use the setter.

e.g.

data class MyModel(val resources: Resources) {
    fun getNameString(): String {
        resources.getString(R.string.someString)
    }
}

2. Use the data-binding (requires fragment/activity though)

Before you read: This version uses 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>

Activity/Fragment-

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

Sometimes, you need to change the text based on a field in a model. So you would data-bind that model as well and since your activity/fragment knows about the model, you can very well fetch the value and then data-bind the string based on that.

Solution 11 - Java

If you want to use getString Outside of a Context or Activity you should have context in constructor or method parameter so that you can access getstring() method. Specially in Fragment You shoud ensure that getActivity() or getContext() are not providing null value. To avoid null from getActivity() or getContext() in a Fragment try this : Declare a variable :

Context mContext;

now override onAttach and onDetach method of Fragment :

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mContext = context;
}

@Override
public void onDetach() {
    super.onDetach();
    mContext = null;
}

Now Use mContext whereever you are using getString() method. ex:

        Toast.makeText(mContext,  mContext.getString(R.string.sample_toast_from_string_file), Toast.LENGTH_SHORT).show();

Solution 12 - Java

Kotlin: Perfect Decision 02.03.2021


  • AppCompatActivity
  • Companion object

Activity code:

class MainActivity : AppCompatActivity() {

    companion object {
        lateinit var instance: AppCompatActivity
            private set
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        instance = this
    }
}

Getting a resource from AnyWhere:

val text = MainActivity.instance.getString(R.string.task_1)

P.S Vel_daN: LOVE WHAT You DO.

Solution 13 - Java

I used getContext().getApplicationContext().getString(R.string.nameOfString); It works for me.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSapphireSunView Question on Stackoverflow
Solution 1 - JavaGangnusView Answer on Stackoverflow
Solution 2 - JavaErich DouglassView Answer on Stackoverflow
Solution 3 - JavakonmikView Answer on Stackoverflow
Solution 4 - JavaKhemraj SharmaView Answer on Stackoverflow
Solution 5 - JavaJan NaruszkiewiczView Answer on Stackoverflow
Solution 6 - JavaMalus JanView Answer on Stackoverflow
Solution 7 - JavaMickael BelhassenView Answer on Stackoverflow
Solution 8 - JavaVersaView Answer on Stackoverflow
Solution 9 - JavaAhmed RazaView Answer on Stackoverflow
Solution 10 - JavaRajkiranView Answer on Stackoverflow
Solution 11 - JavaMANISHView Answer on Stackoverflow
Solution 12 - JavaВладислав ШестернинView Answer on Stackoverflow
Solution 13 - JavavivynzView Answer on Stackoverflow