Getstring Outside of a Context or Activity

getString Outside of a Context or Activity

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.

How to get String in a non activity class?

The issue which you are getting is NullPointerException on _context.

I think it is because you have declared _context as static variable and convertTimeToHoursMinutesString as static method.

But you are initializing the _context in constructor.

public CommonUtils(Context context) {
this._context = context;
}

But as the method is static so you would not be creating an object to call it. Instead you would be calling it directly by class name, like CommonUtils.convertTimeToHoursMinutesString. So the constructor never gets called, hence _context is null.

If you want to keep it static then you can do it like this,

public static String convertTimeToHoursMinutesString(Context _context, long lTimeinMillis){
// Calculate hours first.
long hours = TimeUnit.MILLISECONDS.toHours(lTimeinMillis);
lTimeinMillis -= TimeUnit.HOURS.toMillis(hours);
// Calculate minutes then.
long minutes = TimeUnit.MILLISECONDS.toMinutes(lTimeinMillis);
lTimeinMillis -= TimeUnit.MINUTES.toMillis(minutes);
// Calculate seconds last.
//long seconds = TimeUnit.MILLISECONDS.toSeconds(lTimeinMillis);

StringBuilder str = new StringBuilder(64);
str.append(hours);

str.append(_context.getString(R.string.Hour));
str.append(minutes);
str.append(_context.getString(R.string.Min));
//str.append(seconds);
//str.append(" Seconds");
return(str.toString());
}

Also you can access getString() like context.getResources().getString(R.string.YOUR_STRING);

Accessing Resources without a Context

Use

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

You can use it ABSOLUTELY EVERYWHERE in your application, even in static constants declaration! But for system resources only.

For local resources use that solution.

Android. Get string resource for a non-activity class

You have to use reference to a Context to access resources.
I'd recommend extending the Application class and creating an Application Singleton, then calling:

MyApplication.getInstance().getString(R.string.myString);

Or injecting it into your class of choice.

Problem with this approach is that it would make your class harder to test, since now it uses the Android context. I'd recommend passing a string as a dependency into the non-activity class of choice via the constructor or preferred method.

public MyClass(String string){
}

call getString(R.strings....) from class?

the solution here is to make sure your object has a reference to the application context

Class Swag{
private Context ctx;
public Swag(Context ctx){
this.ctx = ctx;
}
public void doSomething(){
String something = ctx.getResources().getString(R.string.somestring);
...
}
// or like this
public void makeUpperCase(Context appContext){
appContext.getResources().getString(R.string.super_string_swag_yolo);
}
}

obviously you'd have to supply the context when creating an object or when caling the method

Localization of text outside of activities in Android?

getResources(), which you need for the text localization, is the method of the abstract Context class. Activity just inherits it, meaning you don't actually need a reference to an Activity to get the package resources. Application context is enough.

As to using Context in a data layer, you might create an instance (better singleton) of, let's call it ResourceProvider, passing in the application context. For example,

interface ResourceProvider {
fun getString(@StringRes id: Int): String
}

class ResourceProviderImpl constructor(private val context: Context) : ResourceProvider {

override fun getString(id: Int): String = context.getString(id)
}

Just make sure you pass the applicationContext to the constructor of ResourceProviderImpl in order to avoid a memory leak on the context whose lifecycle is shorter than that of the application.

How to use String ressource in Java file in Android without a Layout

getString(R.string...

is not the same as

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

Only the second variant you can use in the static context. Alas, you can get this way only system resources.

If you need to get your own resources, no one-line solution exists. Use https://stackoverflow.com/a/4391811/715269 solution of @Cristian. And notice: it is a very good solution, even more, it is the solution meant to be used by the creators of Android.

Get text from string with kotlin in android studio

use applications context:

private const val TEXT_HEADER = 
getApplicationContext().getResources().getString(R.string.textheader);

app crashes while opening main Activity because of getString(R.string.xxx)

getString requires your Activity to have a Context, and at construction time it doesn't have one. So when you define those top-level variables that are initialised at construction time, your getString calls fail. The error log will tell you this, that you're trying to do something with a null Context or similar.

The context shows up somewhere around onCreate, so if you can guarantee those values won't be used until the Activity is CREATED (i.e. you won't be reading them until onCreate or later) then you could use a lazy delegate. That only initialises them when they're first read - so if you're reading them when the Activity has its Context, the getString call works fine!

val EGP = by lazy { getString(R.string.egyptian_pound_egp) }
val USD = by lazy { getString(R.string.american_dollar_usd) }
val SAR = by lazy { getString(R.string.Saudia_Ryal) }
val KWD = by lazy { getString(R.string.Kuwaiti_Dinar) }

But the problem here is you're not first reading these in onCreate or later - it happens in the next line where you build a Map using those values, which is another top-level variable that's initialised at construction. So you don't get the benefit of the lazy because it's called too early.

You can fix this by making that map lazy too:

val listValue by lazy { mapOf(
USD to 0.052356,
EGP to 1.0,
SAR to 0.197040,
KWD to 0.0166838
)}

Now listValue won't be initialised until it's read either! So it won't try to read those other values until it's actually accessed - so same deal, as long as listValue isn't read by something before onCreate, it should be fine.

This is the kind of thing you have to watch out for with lazy delegates in Android lifecycle components like Activity and Fragment, or anywhere you need lazy initialisation really. Make sure it's not being read too early by something else, and make those lazy too if appropriate.


Using lazy delegates requires your variables to be vals though - if you need to be able to change them, make them lateinit instead and initialise them manually as soon as you can. You could keep listValue as a lazy if you want, just make sure the lateinit vars it initialises from are assigned before it's accessed



Related Topics



Leave a reply



Submit