Home » Android » java – getString Outside of a Context or Activity

java – getString Outside of a Context or Activity

Posted by: admin March 10, 2020 Leave a comment

Questions:

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?

How to&Answers:

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.

Answer:

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.

Answer:

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.

Answer:

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

Answer:

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 getResourses() {
        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.

Answer:

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

Answer:

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

Answer:

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

Answer:

It’s better to use something like this without context and activity:

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

Answer:

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)
    }
}
  1. 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.

Answer:

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)

Answer:

Here’s what I did,
In your MainActivity, create a static variable for context as shown below:

public static Context mContext;

and in the onCreate() initialise mContext to this;

mContext = this;

Then, in the file where you want to access context, say,

private Context context = MainActivity.mContext;

Now, you can get a string resource in the following manner,

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

Answer:

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