When programming for Android sometimes you have to use static methods. But when you try to access you resources in a static method with getString(R.string.text) you'll get an error. Making it static doesn't work.
Does anyone knows a good way around this? The resource files in Android are very helpful for creating things in different languages or making changes to a text.
One way or another, you'll need a Context for that... For static methods this probably means you need to pass along a Context when calling them.
You could use Resources.getSystem().getStringArray(android.R.array.done);
This is how I access resources from inside static methods. Maybe not ideal, but.
First, I extend Application and set some public static field(s), and create a method to initialise them:
public class MyApp extends Application {
// static resources
public static String APP_NAME;
public static void initResources(Context context) {
APP_NAME = context.getResources().getString(R.string.app_name);
}
}
And in my manifest I register the extended Application:
<application
android:name=".MyApp"/>
In my starter activity (MainActivity), I make a call to initialise the static resources:
#Override
protected void onCreate(Bundle savedInstanceState) {
MyApp.initResources(this);
}
Then anywhere in your project, after MainActivity.onCreate(Bundle b) has run, you can call static methods that access your specified static resources:
public static void printAppName() {
Log.w("tag", "my app name: " + MyApp.APP_NAME);
}
Pass in a Context (i.e. Activity) instance as a parameter object to static method. Then invoke getString on the parameter.
The post below gives a tip for creating an Application class to save your current context. Your new Application class will then be accessible from any other static method.
How can I get a resource content from a static context?
One way is you can pass context to your static method.
check this out it definitely works
public class Sounds {
public static MediaPlayer getSoundTouch(Context context){
return MediaPlayer.create(context, R.raw.touch);
}
public static MediaPlayer getSoundLeak(Context context){
return MediaPlayer.create(context, R.raw.leak);
}
public static MediaPlayer getSoundFinish(Context context){
return MediaPlayer.create(context, R.raw.finish);
}
}
Related
I follow Android N change language programmatically to changed language of my app in android N and above. However, I still have the problem with the application context instance.
In my Application class:
private static Application mInstance;
public static Context getApplication() {
return mInstance;
}
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
The language is changed, but Resources get from the Application context is not changed. For example:
MyApplication.getApplication().getResources().getString(stringId);
With return the wrong language string.
Can I update the application instance in this situation? I stuck to this problem for several hours. Because the MyApplication.getApplication() have used in many places throughout my app. So I can't convert to the Activity context.
Many thanks.
I have the same issue with one of my apps, because I do love my managers and utilities that doesn't require the context being passed every time.
My solution involves two separate contexts, one application context and one locale context. This doesn't solve all issues like inflating with correct locale using the correct style, for this you need to use the activity context. However, if you need to get the correct string or image from the resources based on the current locale, then this solution will work.
public class MainApplication extends Application {
private static Context applicationContext;
private static Context localeContext;
public static Context getAppContext() {
return applicationContext;
}
public static Context getLocaleContext() {
return localeContext;
}
#Override
public void onCreate() {
super.onCreate();
setTheme(R.style.AppTheme);
applicationContext = getApplicationContext();
updateLocaleContext();
}
public static void updateLocaleContext() {
localeContext = LocaleHelper.wrapContext(applicationContext);
}
}
The LocaleHelper.wrapContext should use a similar solution as the accepted answer on Android N change language programmatically and all activites need to implements attachBaseContext. Every time the language changes MainApplication.updateLocaleContext needs to be called. Note: the localeContext do not retain the style set in the onCreate function
Now you can use the MainApplication.getLocaleContext() for resources that depend on correct locale, while using MainApplication.getAppContext() for, e.g., inflating views that do not depend on the locale. Note: you could also place the localeContext in LocaleHelper to reduce the coupling
I have a class called myConstants and in it i list all my constants so when i need them I just reference MyConstants.MYCONSTANT. However, i would like to implement something like this for methods. i am repeating a lot of code, for instance, i have a formatCalendarString(Calendar c) method in 3 activities. seems redundant and unecessary. but i cant make them static because i get static calling non-static errors and the only other way i can think is to make a MyConstant object then call public functions off that object, like this...
MyConstants myConstants = new MyConstants();
myConstants.formatCalendarString(Calendar.getInstance());
is there some way i can just call the formatCalendarString() inside MyConstants class without generating an object?
You can use singleton pattern to cache instances. Keeping methods in something like parent activity does not make any sense (as primary role of activity is user interaction).
Example:
public class MyConstants {
private static MyConstants ourInstance;
private MyConstants() {
//private constructor to limit direct instantiation
}
public synchronized static MyConstants getInstance() {
//if null then only create instance
if (ourInstance ==null) {
ourInstance = new MyConstants();
}
//otherwise return cached instance
return ourInstance;
}
}
You just need a private constructor and public static method that would only generate instance if it is null.
Then, call MyConstants.getInstance().whateverMethod(). It will create only single instance.
However when using singleton, please keep memory leaks in mind. Do not pass activity context directly inside singletons.
If you want to have all methods in activities, you can put then in abstract class BaseActivity, which extends Activity, and then make your activities extends BaseActivity. However, if these methods doesn't correspond to something about activity, I suggest some Singleton or Util class
I agree with Pier Giorgio Misley. It's also good to add a private constructor, because you don't obviously want to instantiate an object.
Can't you just use a parent class? That way you can just inherit the methods and manage in one source. Then you don't have to use static functions then.
Edit: Like Tomasz Czura said, just extend the Class.
public class ParentClass {
public void commonMethod(){
}
}
public class OtherClass extends ParentClass{
}
You can use the Static keyword.
Static methods can be referenced from outside without istantiating the new object.
Just create a class:
public class MyClassContainingMethods{
public static String MyStaticMethod(){
return "I am static!";
}
}
Now call it like
String res = MyClassContainingStaticMethods.MyStaticMethod();
Hope this helps
NOTE
You CAN call non-static from static by doing something like this:
public static void First_function(Context context)
{
SMS sms = new SMS();
sms.Second_function(context);
}
public void Second_function(Context context)
{
Toast.makeText(context,"Hello",1).show(); // This i anable to display and cause crash
}
Example taken from here, you will obiouvsly have to fit it into your needs
I have a class that needs to obtain a reference to it's application's AssetManager. This class does not extend any sort of android UI class, so it doesn't have a getContext() method, or anything similar. Is there some sort of static Context.getCurrentApplicationContext() type of method?
To clarify: my class is intended to be used like a library, for other applications. It has no associated AndroidManifest.xml or control over the context which is calling it.
Create a subclass of Application, for instance public class App extends Application {
Set the android:name attribute of your <application> tag in the AndroidManifest.xml to point to your new class, e.g. android:name=".App"
In the onCreate() method of your app instance, save your context (e.g. this) to a static field named app and create a static method that returns this field, e.g. getApp():
This is how it should look:
public class App extends Application{
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
Now you can use: App.getContext() whenever you want to get a context, and then getAssetManager() (or App.getContext().getAssetManager()).
I am not sure of the best answer to the OP question. However, I do know that you have to be very careful when using a static context as suggested in Android developer resources:
In the onCreate() method of your app instance, save your context (e.g. this) to a static field named app and create a static method that returns this field, e.g. getApp():
Using static contexts can leak to leaked memory issues, especially if the static context is used for references to views.
I'm working on an Android application that has several Activities. In it I have a class with several static methods. I would like to be able to call these methods from the different Activities. I'm using the static methods to load data from an xml file via a XmlResourceParser. To create a XmlResourceParser requires a call on the Application Context. So my question is, what is the best way to get a reference to the Application Context into the static methods? Have each Activity get it and pass it in? Store it somehow in a global variable?
The better way would be to pass the Activity object as parameter to the static functions.
AFAIK, there is no such method which will give you the application context in the static method.
This should get you access to applicationContext from anywhere allowing you to get applicationContext anywhere that can use it; Toast, getString(), sharedPreferences, etc. I have used this to get applicationContext inside of static methods multiple times.
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. :)
I am not sure this is going to work all the time but it works for me now:
public class myActivity extends ListActivity
{
public static Context baseContext;
public void onCreate(Bundle savedInstanceState)
{
baseContext = getBaseContext();
}
Then you may use the static in your package:
myApplication.baseContext
There's a post in Sane Tricks For InsaneWorld blog with an answer.
It says you can replace the Application object with your own subclass and then keep the app context statically there.
You can find example code in the post.
The original blog post - http://uquery.blogspot.co.il/2011/08/how-to-get-application-context.html
In an Android app, is there anything wrong with the following approach:
public class MyApp extends android.app.Application {
private static MyApp instance;
public MyApp() {
instance = this;
}
public static Context getContext() {
return instance;
}
}
and pass it everywhere (e.g. SQLiteOpenHelper) where context is required (and not leaking of course)?
There are a couple of potential problems with this approach, though in a lot of circumstances (such as your example) it will work well.
In particular you should be careful when dealing with anything that deals with the GUI that requires a Context. For example, if you pass the application Context into the LayoutInflater you will get an Exception. Generally speaking, your approach is excellent: it's good practice to use an Activity's Context within that Activity, and the Application Context when passing a context beyond the scope of an Activity to avoid memory leaks.
Also, as an alternative to your pattern you can use the shortcut of calling getApplicationContext() on a Context object (such as an Activity) to get the Application Context.
In my experience this approach shouldn't be necessary. If you need the context for anything you can usually get it via a call to View.getContext() and using the Context obtained there you can call Context.getApplicationContext() to get the Application context. If you are trying to get the Application context this from an Activity you can always call Activity.getApplication() which should be able to be passed as the Context needed for a call to SQLiteOpenHelper().
Overall there doesn't seem to be a problem with your approach for this situation, but when dealing with Context just make sure you are not leaking memory anywhere as described on the official Google Android Developers blog.
Some people have asked: how can the singleton return a null pointer?
I'm answering that question. (I cannot answer in a comment because I need to post code.)
It may return null in between two events: (1) the class is loaded, and (2) the object of this class is created. Here's an example:
class X {
static X xinstance;
static Y yinstance = Y.yinstance;
X() {xinstance=this;}
}
class Y {
static X xinstance = X.xinstance;
static Y yinstance;
Y() {yinstance=this;}
}
public class A {
public static void main(String[] p) {
X x = new X();
Y y = new Y();
System.out.println("x:"+X.xinstance+" y:"+Y.yinstance);
System.out.println("x:"+Y.xinstance+" y:"+X.yinstance);
}
}
Let's run the code:
$ javac A.java
$ java A
x:X#a63599 y:Y#9036e
x:null y:null
The second line shows that Y.xinstance and X.yinstance are null; they are null because the variables X.xinstance ans Y.yinstance were read when they were null.
Can this be fixed? Yes,
class X {
static Y y = Y.getInstance();
static X theinstance;
static X getInstance() {if(theinstance==null) {theinstance = new X();} return theinstance;}
}
class Y {
static X x = X.getInstance();
static Y theinstance;
static Y getInstance() {if(theinstance==null) {theinstance = new Y();} return theinstance;}
}
public class A {
public static void main(String[] p) {
System.out.println("x:"+X.getInstance()+" y:"+Y.getInstance());
System.out.println("x:"+Y.x+" y:"+X.y);
}
}
and this code shows no anomaly:
$ javac A.java
$ java A
x:X#1c059f6 y:Y#152506e
x:X#1c059f6 y:Y#152506e
BUT this is not an option for the Android Application object: the programmer does not control the time when it is created.
Once again: the difference between the first example and the second one is that the second example creates an instance if the static pointer is null. But a programmer cannot create the Android application object before the system decides to do it.
UPDATE
One more puzzling example where initialized static fields happen to be null.
Main.java:
enum MyEnum {
FIRST,SECOND;
private static String prefix="<", suffix=">";
String myName;
MyEnum() {
myName = makeMyName();
}
String makeMyName() {
return prefix + name() + suffix;
}
String getMyName() {
return myName;
}
}
public class Main {
public static void main(String args[]) {
System.out.println("first: "+MyEnum.FIRST+" second: "+MyEnum.SECOND);
System.out.println("first: "+MyEnum.FIRST.makeMyName()+" second: "+MyEnum.SECOND.makeMyName());
System.out.println("first: "+MyEnum.FIRST.getMyName()+" second: "+MyEnum.SECOND.getMyName());
}
}
And you get:
$ javac Main.java
$ java Main
first: FIRST second: SECOND
first: <FIRST> second: <SECOND>
first: nullFIRSTnull second: nullSECONDnull
Note that you cannot move the static variable declaration one line upper, the code will not compile.
Application Class:
import android.app.Application;
import android.content.Context;
public class MyApplication extends Application {
private static Context mContext;
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
public static Context getAppContext() {
return mContext;
}
}
Declare the Application in the AndroidManifest:
<application android:name=".MyApplication"
...
/>
Usage:
MyApplication.getAppContext()
You are trying to create a wrapper to get Application Context and there is a possibility that it might return "null" pointer.
As per my understanding, I guess its better approach to call- any of the 2
Context.getApplicationContext() or Activity.getApplication().
It is a good approach. I use it myself as well. I would only suggest to override onCreate to set the singleton instead of using a constructor.
And since you mentioned SQLiteOpenHelper: In onCreate () you can open the database as well.
Personally I think the documentation got it wrong in saying that There is normally no need to subclass Application. I think the opposite is true: You should always subclass Application.
I would use Application Context to get a System Service in the constructor. This eases testing & benefits from composition
public class MyActivity extends Activity {
private final NotificationManager notificationManager;
public MyActivity() {
this(MyApp.getContext().getSystemService(NOTIFICATION_SERVICE));
}
public MyActivity(NotificationManager notificationManager) {
this.notificationManager = notificationManager;
}
// onCreate etc
}
Test class would then use the overloaded constructor.
Android would use the default constructor.
I like it, but I would suggest a singleton instead:
package com.mobidrone;
import android.app.Application;
import android.content.Context;
public class ApplicationContext extends Application
{
private static ApplicationContext instance = null;
private ApplicationContext()
{
instance = this;
}
public static Context getInstance()
{
if (null == instance)
{
instance = new ApplicationContext();
}
return instance;
}
}
I'm using the same approach, I suggest to write the singleton a little better:
public static MyApp getInstance() {
if (instance == null) {
synchronized (MyApp.class) {
if (instance == null) {
instance = new MyApp ();
}
}
}
return instance;
}
but I'm not using everywhere, I use getContext() and getApplicationContext() where I can do it!
I know the original question was posted 13 years ago, and this is the Kotlin version of getting context everywhere.
class MyApplication : Application() {
companion object {
#JvmStatic
private var instance: MyApplication? = null
#JvmStatic
public final fun getContext(): Context? {
return instance
}
}
override fun onCreate() {
instance = this
super.onCreate()
}
}