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 val
s 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 var
s it initialises from are assigned before it's accessed
Related Topics
Collections Sort(List<T>,Comparator<? Super T>) Method Example
Background Timer Task in Jsp/Servlet Web Application
Java: Why Do You Need to Specify an 'F' in a Float Literal
How to Initialize List<String> Object in Java
Javafx CSS Error ( Property Stylesheets Does Not Exist )
Screen Video Record of Current Activity Android
Android Resource - Array of Arrays
Send Sms Until It Is Successful
How to Send Data from Dialogfragment to a Fragment
Can't Get Download Url from Firebase Storge in Android
How to Start Activity in Adapter
Android:Change App Label Programmatically
What Kind of Ocr Java Library Should I Use in Android
Android Fragmentmanager Backstackrecord.Run Throwing Nullpointerexception